diff --git a/android_crop_lib/build.gradle b/android_crop_lib/build.gradle index 17b97a7a0..a52b7c7a3 100644 --- a/android_crop_lib/build.gradle +++ b/android_crop_lib/build.gradle @@ -5,7 +5,7 @@ android { compileSdkVersion 29 defaultConfig { - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 testApplicationId 'com.soundcloud.android.crop.test' diff --git a/app/aliyun-libs/SudMGP-v1.1.31.181.aar b/app/aliyun-libs/SudMGP-v1.1.31.181.aar new file mode 100644 index 000000000..1e5879f7d Binary files /dev/null and b/app/aliyun-libs/SudMGP-v1.1.31.181.aar differ diff --git a/app/build.gradle b/app/build.gradle index 17c84d429..434ab76bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { defaultConfig { applicationId "com.mango.yinyou" - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionCode Integer.valueOf(version_code) versionName version_name @@ -294,6 +294,8 @@ dependencies { implementation files('libs/humesdk-1.0.0.aar') + implementation(name: 'SudMGP-v1.1.31.181', ext: 'aar') + // xplan flutter module if (useFlutterAar) { implementation 'com.mango.flutter.xplan:flutter_release:1.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0caf31dc9..82549c31d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -89,6 +89,7 @@ android:supportsRtl="true" android:theme="@style/MyMaterialTheme" android:usesCleartextTraffic="true" + android:networkSecurityConfig="@xml/network_security_config" tools:replace="android:name, android:allowBackup"> (), + View.OnClickListener, OnGiftDialogBtnClickListener, IGameRoomView, OnMicroItemClickListener { + private var myUid: Long = 0 + private lateinit var messageView: MessageView + private lateinit var bottomView: BottomView + private lateinit var inputLayout: RelativeLayout + private lateinit var inputEdit: EditText + private lateinit var inputSend: ImageView + private lateinit var microView: MicroView + private var mDisposable: Disposable? = null + private lateinit var gameBinding: FragmentGameRoomBinding + private var isCloseScreen = false + private var isOpenRedPackage = false + private var isRoomMin = false + + private lateinit var gameDelegate: GameDelegate + + /** + * 是否开启礼物值显示 + */ + private var showGiftValue = false + private var redPackageSendDialog: RedPackageSendDialog? = null + private val mOnSoftKeyBoardChangeListener: OnSoftKeyBoardChangeListener = + object : OnSoftKeyBoardChangeListener { + override fun keyBoardShow(height: Int) { + /*软键盘显示:执行隐藏title动画,并修改listview高度和装载礼物容器的高度*/ + } + + override fun keyBoardHide(height: Int) { + /*软键盘隐藏:隐藏聊天输入框并显示聊天按钮,执行显示title动画,并修改listview高度和装载礼物容器的高度*/ + inputLayout.visibility = View.GONE + } + } + private var dynamicFaceDialog: DynamicFaceDialog? = null + private var giftDialog: GiftDialog? = null + override fun getRootLayoutId(): Int { + return R.layout.fragment_game_room + } + + override fun onFindViews() { + gameBinding = DataBindingUtil.bind(mView)!! + gameBinding.lifecycleOwner = this + gameBinding.click = this + gameBinding.ktvModel = false + messageView = mView.findViewById(R.id.message_view) + bottomView = mView.findViewById(R.id.bottom_view) + inputLayout = mView.findViewById(R.id.input_layout) + inputEdit = mView.findViewById(R.id.input_edit) + inputSend = mView.findViewById(R.id.input_send) + microView = mView.findViewById(R.id.micro_view) + messageView.setClickConsumer { + if (!TextUtils.isEmpty(it) && it != "0") { + showUserCardDialog(it) + } + } + messageView.setOnClick(object : MessageView.OnClick { + override fun onFollowClick(position: Int) { + mvpPresenter?.followOwner(position, AvRoomDataManager.get().roomUid) + } + + override fun onJoinMiniWorldClick(position: Int) {} + override fun onShowRoomIntroduction() { + showRoomIntroduction(false) + } + }) + + messageView.setOnClickListener { + messageView.updateLayoutParams { + height = ScreenUtil.dip2px(200f) + } + } + + gameDelegate = GameDelegate(requireActivity(), gameBinding.flGameContainer) + } + + override fun onSetListener() { + bottomView.setBottomViewListener(GameRoomBottomViewWrapper()) + bottomView.setMagicBtnEnable(true) + inputSend.setOnClickListener(this) + + inputLayout.setOnTouchListener { _: View?, _: MotionEvent? -> + inputEdit.clearFocus() + inputLayout.setVisibility(View.GONE) + KeyBoardUtils.hideKeyBoard(getActivity(), inputEdit) + false + } + softKeyboardListener() + } + + + override fun onInitArguments(bundle: Bundle?) { + super.onInitArguments(bundle) + if (bundle != null) { + isRoomMin = bundle.getBoolean(Constants.IS_ROOM_MIN, false) + } + } + + @SuppressLint("CheckResult") + override fun initiate() { + //如果不需要开麦,并且还没有权限的情况下,重置状态为需要去打开麦克风 + if (!AvRoomDataManager.get().mIsNeedOpenMic && !isHavingMicPermissions) { + AvRoomDataManager.get().mIsNeedOpenMic = true + } + myUid = AuthModel.get().currentUid + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + isCloseScreen = AvRoomDataManager.get().isCloseScreen + isOpenRedPackage = AvRoomDataManager.get().isOpenRedPackage + showGiftValue = AvRoomDataManager.get().isShowGiftValue + openOrCloseGiftValue(true) + updateView() + updateMicBtn() + microView.setOnMicroItemClickListener(this) + mDisposable = IMNetEaseManager.get().chatRoomEventObservable + .subscribe { onReceiveRoomEvent(it) } + if ((AvRoomDataManager.get().mCurrentRoomInfo != null + ) && (IMNetEaseManager.get().mCacheRoomQueueInfo != null + ) && !AvRoomDataManager.get() + .isFirstEnterRoomOrChangeOtherRoom( + AvRoomDataManager.get().mCurrentRoomInfo?.uid ?: 0 + ) + ) { + mvpPresenter?.chatRoomReConnect(IMNetEaseManager.get().mCacheRoomQueueInfo) + } + + // 接收公屏消息点击 可点击房间编辑页查看 事件 + RxBus.get().toFlowable(OpenRoomIntroEvent::class.java) + .compose(bindToLifecycle()) + .subscribe { showRoomIntroduction(false) } + + RxBus.get().toFlowable(ShowGiftDialogEvent::class.java) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { onSendGiftBtnClick() } + + RxBus.get().toFlowable(ShowUserInfoDialogEvent::class.java) + .compose(bindUntilEvent(FragmentEvent.DESTROY_VIEW)) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { showUserCardDialog(it.getUid()) } + + // 刷新礼物列表,获取房间专属礼物列表 + GiftModel.get().refreshGiftList(AvRoomDataManager.get().roomUid.toString()).subscribe() + checkFollowOwner() + mvpPresenter?.loadMessageHistory() + + //最小化恢复时,更新礼物值 + if (isRoomMin) { + GiftValueMrg.get().updateRoomGiftValue(false) + } + + gameBinding.microView.bindAdapter(GameMicroViewAdapter(context)) + + gameBinding.tvShowMiniMic.setOnClickListener { + gameBinding.microView.bindAdapter(GameMiniMicroViewAdapter(context)) + gameBinding.tvShowMiniMic.isVisible = false + gameBinding.microView.updateLayoutParams { + width = LinearLayout.LayoutParams.WRAP_CONTENT + marginStart = ScreenUtil.dip2px(2f) + marginEnd = ScreenUtil.dip2px(2f) + } + gameBinding.microView.postDelayed({ + gameBinding.ivShowMic.isVisible = true + gameBinding.llMicView.setBackgroundResource(R.drawable.bg_mini_mic_entrance) + }, 100) + } + + gameBinding.ivShowMic.setOnClickListener { + gameBinding.microView.updateLayoutParams { + width = LinearLayout.LayoutParams.MATCH_PARENT + marginStart = ScreenUtil.dip2px(10f) + marginEnd = ScreenUtil.dip2px(10f) + } + gameBinding.microView.bindAdapter(GameMicroViewAdapter(context)) + gameBinding.tvShowMiniMic.isVisible = true + gameBinding.llMicView.background = null + gameBinding.ivShowMic.isVisible = false + + } + } + + private fun onReceiveRoomEvent(roomEvent: RoomEvent?) { + if (roomEvent == null) return + val event = roomEvent.event + when (event) { + RoomEvent.ROOM_CHAT_RECONNECTION -> { + // 重新调服务器的userroom/inV2,保持座位上有贵族 + mvpPresenter?.userRoomIn() + //从新获取队列信息 + mvpPresenter?.chatRoomReConnect(roomEvent.roomQueueInfo) + //如果用户在麦上的话,会重新上麦一次,如果不在麦上,则自行更新 + if (RxNetWorkUtils.isAvailable(mContext) && !AvRoomDataManager.get().isOwnerOnMic) { + GiftValueMrg.get().handleReconnect(false) + } + } + RoomEvent.ROOM_EXIT -> { + // 退出房间,把标志置为 false + AvRoomDataManager.get().isFromMentoring = false + // 退出房间的时候,要停止倒计时 + EventBus.getDefault().post(MentoringStopCountingEvent()) + } + RoomEvent.DOWN_CROWDED_MIC -> if (AvRoomDataManager.get().isOwner(roomEvent.account)) { + toast(R.string.crowded_down) + } + RoomEvent.ROOM_MANAGER_ADD, RoomEvent.ROOM_MANAGER_REMOVE -> { + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + updateView() + } + RoomEvent.ROOM_INFO_UPDATE -> { + Logger.i("房间更新事件") + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + updateScreen() + updateRedPackage() + updateView() + updateRemoteMuteBtn() + openOrCloseGiftValue(false) + } + RoomEvent.ENTER_ROOM -> { + Logger.i("进入房间事件") + gameBinding.roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + updateView() + updateRemoteMuteBtn() + openOrCloseGiftValue(true) + GiftValueMrg.get().updateRoomGiftValue(false) + } + RoomEvent.ADD_BLACK_LIST -> onChatRoomMemberBlackAdd(roomEvent.account) + RoomEvent.MIC_QUEUE_STATE_CHANGE -> onQueueMicStateChange( + roomEvent.micPosition, + roomEvent.posState + ) + RoomEvent.KICK_DOWN_MIC_BY_S_ADMIN, RoomEvent.KICK_DOWN_MIC -> if (event == RoomEvent.KICK_DOWN_MIC) { + SingleToastUtil.showToast( + mContext.resources.getString( + R.string.kick_mic + ) + ) + } else if (event == RoomEvent.KICK_DOWN_MIC_BY_S_ADMIN) { + SingleToastUtil.showToast( + mContext.resources.getString( + R.string.kick_mic_by_s_admin + ) + ) + } + RoomEvent.DOWN_MIC -> { + addOrRemoveMatchPool() + onDownMicro(roomEvent.micPosition) + } + RoomEvent.UP_MIC -> { + addOrRemoveMatchPool() + onUpMicro(roomEvent.micPosition) + } + RoomEvent.INVITE_UP_MIC -> if (AvRoomDataManager.get().isOwner(roomEvent.account)) { + //自己的消息 + onInviteUpMic(roomEvent.micPosition) + } + RoomEvent.KICK_OUT_ROOM -> { + val reason = roomEvent.reason + if (reason != null && reason.reason == ChatRoomKickOutEvent.ChatRoomKickOutReason.CHAT_ROOM_INVALID) { + releaseView() + } + if (AvRoomDataManager.get().isQueuingMicro && AvRoomDataManager.get().myIsInQueue) { + MicQueueModel.get().cancelApplyForQueuing( + AvRoomDataManager.get().roomUid, + AuthModel.get().currentUid + ).subscribe() + } + if (AvRoomDataManager.get().isFromMentoring && !(AuthModel.get().currentUid == AvRoomDataManager.get().mCurrentRoomInfo?.uid)) { + // 被踢出房间的时候,要停止倒计时 + EventBus.getDefault().post(MentoringStopCountingEvent()) + // 并且把标志置为 false + AvRoomDataManager.get().isFromMentoring = false + } + AvRoomDataManager.get().removeChatRoomMember(roomEvent.account.toString()) + } + RoomEvent.ON_NOBLE_MEMBER_IN -> { + } + RoomEvent.ON_QUEUE_MEMBER_INFO_UPDATE -> // 用户的贵族字段过期或者开通贵族,可以实时地监听ext字段变化,显示头饰,光晕等 + microView.adapter.notifyDataSetChanged() + RoomEvent.OTHER_KICK_OUT_ROOM, RoomEvent.OTHER_ADD_BLACK, RoomEvent.OTHER_KICK_OUT_OR_ADD_BLACK_BY_S_ADMIN -> { + val targetUid = roomEvent.account + if (!TextUtils.isEmpty(targetUid)) { + AvRoomDataManager.get().removeChatRoomMember(targetUid) + } + } + RoomEvent.LEAVE_MODE -> microView.adapter.notifyDataSetChanged() + else -> { + } + } + } + + /** + * 开启或关闭公屏 + */ + private fun updateScreen() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null || + isCloseScreen == AvRoomDataManager.get().mCurrentRoomInfo?.isCloseScreen + ) return + isCloseScreen = AvRoomDataManager.get().mCurrentRoomInfo?.isCloseScreen == true + if (isCloseScreen) { + AvRoomDataManager.get().chatRoomDataRelease(false) + gameBinding.messageView.clear() + } + mvpPresenter?.updateScreen(isCloseScreen) + } + + private fun updateRedPackage() { + if (AvRoomDataManager.get().mCurrentRoomInfo == null || + isOpenRedPackage == AvRoomDataManager.get().mCurrentRoomInfo?.isServerRedEnvelopeSwitch + ) return + isOpenRedPackage = + AvRoomDataManager.get().mCurrentRoomInfo?.isServerRedEnvelopeSwitch == true + } + + /** + * 嗨聊房切换清屏方法 + */ + private fun clearScreen() { + gameBinding.messageView.clear() + } + + /** + * 嗨聊房切换重置公屏消息(绿色公告) + */ + private fun addMessage(msg: ChatRoomMessage?) { + gameBinding.messageView.addMessages(msg) + } + + /** + * 开启或关闭礼物值 + */ + private fun openOrCloseGiftValue(isEnterRoom: Boolean) { + if (AvRoomDataManager.get().isOpenKTV || AvRoomDataManager.get().isCpRoom) { + GiftValueMrg.get().clearObsever() + return + } + if (!isEnterRoom && + (AvRoomDataManager.get().mCurrentRoomInfo == null + || showGiftValue == AvRoomDataManager.get().isShowGiftValue) + ) return + showGiftValue = AvRoomDataManager.get().isShowGiftValue + GiftValueMrg.get().openOrCloseGiftValue() + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + // 释放公屏和麦上的所有信息信息和动画 + val roomUid = intent.getLongExtra(Constants.ROOM_UID, 0) + if (roomUid != 0L && roomUid != AvRoomDataManager.get().mCurrentRoomInfo?.uid) { + releaseView() + } + } + + /** + * 显示活动图标 + */ + fun showActivity(dialogInfo: List) { + initRoomAct(gameBinding.activityImg, dialogInfo, 11f) + } + + fun initRoomAct(rollPagerView: RollPagerView, dialogInfo: List, bottomDp: Float) { + rollPagerView.visibility = View.INVISIBLE + if (!ListUtils.isListEmpty(dialogInfo) && !MarketVerifyModel.get().isMarketChecking) { + // 只有一个图标,隐藏底部指示器 + val show = dialogInfo.size > 1 + rollPagerView.setHintView(object : ColorPointHintView( + mContext, Color.WHITE, mContext.resources.getColor( + R.color.color_66FFFFFF + ) + ) { + override fun makeFocusDrawable(): Drawable? { + val dotFocus = GradientDrawable() + dotFocus.setColor(Color.WHITE) + dotFocus.cornerRadius = Util.dip2px( + context, 2f + ).toFloat() + dotFocus.setSize( + Util.dip2px(context, 9f), Util.dip2px( + context, 4f + ) + ) + return if (show) dotFocus else null + } + + override fun makeNormalDrawable(): Drawable? { + val dotNormal = GradientDrawable() + dotNormal.setColor(mContext.resources.getColor(R.color.color_66FFFFFF)) + dotNormal.cornerRadius = Util.dip2px( + context, 2f + ).toFloat() + dotNormal.setSize( + Util.dip2px(context, 4f), Util.dip2px( + context, 4f + ) + ) + return if (show) dotNormal else null + } + }) + val bannerAdapter = RoomActAdapter(mContext, dialogInfo) + rollPagerView.setAdapter(bannerAdapter) + rollPagerView.setPlayDelay(3000) + //设置透明度 + rollPagerView.setAnimationDurtion(500) + bannerAdapter.notifyDataSetChanged() + bannerAdapter.setRoomActClickListener(RoomActClickListener { url -> + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_ROOM_PROMOTE_CLICK, "语音房_推广入口") + DialogWebViewActivity.start(mContext, url) + }) + + // 模拟指示器在viewpager底部效果 + val viewPager = rollPagerView.viewPager + viewPager.offscreenPageLimit = dialogInfo.size + val layoutParams = viewPager.layoutParams as RelativeLayout.LayoutParams + layoutParams.setMargins(0, 0, 0, UIUtil.dip2px(mContext, bottomDp.toDouble())) + viewPager.layoutParams = layoutParams + } + } + + private fun releaseView() { + messageView.release() + microView.release() + } + + private fun updateView() { + // 更新底栏 + showBottomViewForDifRole() + microView.adapter.notifyDataSetChanged() + microView.updateRoomInfo() + } + + /** + * 根据角色显示不同的状态 + */ + private fun showBottomViewForDifRole() { + val isOnMic = AvRoomDataManager.get().isOnMic(myUid) + // 更新播放器界面 + val mCurrentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo ?: return + if (isOnMic) { + bottomView.showHomePartyUpMicBottom() + } else { + bottomView.showHomePartyDownMicBottom() + } + bottomView.showInputOrIcon(isOnMic) + // 更新听筒消息 + bottomView.setRemoteMuteOpen(!AudioEngineManager.get().isRemoteMute) + } + + /** + * 检查是否关注房主,然后弹出 + */ + private fun checkFollowOwner() { + val currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo ?: return + //如果当前账号是房主也过滤 + if (AvRoomDataManager.get().isRoomOwner) { + return + } + mvpPresenter?.checkFollow(currentRoomInfo.uid) + } + + private fun updateMicBtn() { + val currentRoomInfo = AvRoomDataManager.get().mCurrentRoomInfo + if (currentRoomInfo != null) { + if (AudioEngineManager.get().isAudienceRole) { + bottomView.setMicBtnEnable(false) + bottomView.setMicBtnOpen(false) + } else { + val roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByAccount(myUid.toString()) + if (((roomQueueInfo != null) && (roomQueueInfo.mChatRoomMember != null + ) && (myUid.toString() == roomQueueInfo.mChatRoomMember.account) + && (roomQueueInfo.mRoomMicInfo != null + ) && roomQueueInfo.mRoomMicInfo.isMicMute) + ) { + //先判断坑位是否被闭麦了 + bottomView.setMicBtnEnable(false) + bottomView.setMicBtnOpen(false) + } else { + bottomView.setMicBtnEnable(true) + if (AudioEngineManager.get().isMute) { + bottomView.setMicBtnOpen(false) + } else { + //获取当前是否有麦克风权限 + val isPermission = isHavingMicPermissions + if (!isPermission) { + AudioEngineManager.get().isMute = true + } + bottomView.setMicBtnOpen(isPermission) + } + } + } + } else { + bottomView.setMicBtnEnable(false) + bottomView.setMicBtnOpen(false) + } + } + + private fun updateRemoteMuteBtn() { + if (AvRoomDataManager.get().mCurrentRoomInfo != null) { + bottomView.setRemoteMuteOpen(!AudioEngineManager.get().isRemoteMute) + } + } + + fun onMicStateChanged() { + updateMicBtn() + } + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + EventBus.getDefault().register(this) + } + + override fun onStart() { + super.onStart() + gameDelegate.onStart() + } + + override fun onResume() { + super.onResume() + gameDelegate.onResume() + updateMicBtn() + val chatRoomStatusChangeData = AvRoomDataManager.get().chatRoomStatusChangeData + if (chatRoomStatusChangeData != null && + chatRoomStatusChangeData.status == StatusCode.LOGINED + ) { + // 重新调服务器的userroom/inV2,保持座位上有贵族 + mvpPresenter?.userRoomIn() + } + } + + + override fun onPause() { + super.onPause() + gameDelegate.onPause() + } + + override fun onStop() { + super.onStop() + gameDelegate.onPause() + } + + override fun onDestroyView() { + super.onDestroyView() + releaseView() + } + + override fun onDestroy() { + gameDelegate.onDestroy() + mDisposable?.dispose() + mDisposable = null + EventBus.getDefault().unregister(this) + super.onDestroy() + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onAntiSpamEvent(event: AntiSpamEvent?) { + SingleToastUtil.showToast("发送失败,音游提醒您文明用语~") + } + + /** + * 清除公屏信息 + */ + @Subscribe(threadMode = ThreadMode.MAIN) + fun onClearScreenEvent(event: RoomClearScreenEvent?) { + clearScreen() + val firstMsg = IMNetEaseManager.get().firstMessageContent + addMessage(firstMsg) + } + + override fun onClick(v: View) { + when (v.id) { + R.id.input_send -> { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_ROOM_CHAT_CLICK, "语音房_公屏发言") + sendMsg() + } + R.id.iv_ktv_contribute_list, R.id.contribute_list -> { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_RANKING_LIST_CLICK, "房间榜") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_RANKING_LIST_CLICK, "房间榜") + if (childFragmentManager.findFragmentByTag("dialog_fragment_room_rank") != null) { + return + } + val roomRankDialogFragment = RoomRankDialogFragment.newInstance() + roomRankDialogFragment.show(childFragmentManager, "dialog_fragment_room_rank") + } + R.id.tv_room_introduction -> showRoomIntroduction(AvRoomDataManager.get().isRoomOwner || AvRoomDataManager.get().isRoomAdmin) + else -> { + } + } + } + + private fun sendMsg() { + sendMsg(gameBinding.inputEdit.text.toString()) + } + + @SuppressLint("CheckResult") + private fun sendMsg(msg: String) { + if (!AuthModel.get().isImLogin) { + SingleToastUtil.showToast("网络异常,请重试!") + return + } + if (TextUtils.isEmpty(msg)) { + SingleToastUtil.showToast("请输入要发送的内容哦~") + return + } + val roomInfo = AvRoomDataManager.get().mCurrentRoomInfo ?: return + if (roomInfo.isCloseScreen) { + toast("房间公屏已关闭") + return + } + mvpPresenter?.sendTextMsg(msg) + messageView.setNeedAutoScroll(true) // 发送后自动滚动公屏列表 + inputEdit.setText("") + } + + /** + * 软键盘显示与隐藏的监听 + */ + private fun softKeyboardListener() { + SoftKeyBoardListener.setListener(activity, mOnSoftKeyBoardChangeListener) + } + + @SuppressLint("CheckResult") + override fun onSendGiftBtnClick( + giftInfo: GiftInfo, micMemberInfos: List, + number: Int, msg: String, isKnap: Boolean, + isWholdMic: Boolean, callback: SenGiftCallback + ) { + val targetUids: MutableList = ArrayList() + for (i in micMemberInfos.indices) { + targetUids.add(micMemberInfos[i].account.toLong()) + } + val canUseNobleGiftOrNot = GiftModel.get().canUseNobleGiftOrNot(giftInfo) + if (canUseNobleGiftOrNot) { + GiftModel.get() + .sendRoomGift(giftInfo.giftId, targetUids, number, msg, isKnap, isWholdMic) + .compose(bindUntilEvent(FragmentEvent.DESTROY)) + .subscribe(object : BiConsumer?, Throwable?> { + @Throws(Exception::class) + override fun accept( + giftMultiReceiverInfoServiceResult: ServiceResult?, + throwable: Throwable? + ) { + if (throwable != null) { + callback.onFail() + return + } + callback.onSuccess() + } + }) + } else { + val userInfo = UserModel.get().cacheLoginUserInfo + val currentLevel = + if (userInfo == null) 0 else if (userInfo.nobleInfo == null) 0 else userInfo.nobleInfo.level + OpenNobleDialog(mContext, currentLevel, giftInfo.level, "送该礼物").show() + callback.onFail() + } + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.roomcp_gift_open_click, "礼物面板按钮") + } + } + + override fun onSendMagicBtnClick( + magicInfo: MagicInfo, + targetUid: Long, + callback: SenGiftCallback + ) { + } + + fun onUpMicro(micPosition: Int) { + showBottomViewForDifRole() + updateMicBtn() + microView.adapter.notifyDataSetChanged() + } + + fun onInviteUpMic(micPosition: Int) { + AvRoomDataManager.get().mIsNeedOpenMic = true + mvpPresenter?.upMicroPhone(micPosition, AuthModel.get().currentUid.toString(), true) + if (UIUtils.isTopActivity(baseActivity)) { + (activity as BaseMvpActivity<*, *>?)?.dialogManager + ?.showOkWithTitleDialog(getString(R.string.embrace_on_mic), true) + } + } + + fun onDownMicro(micPosition: Int) { + showBottomViewForDifRole() + updateMicBtn() + gameBinding.microView.removeDragonBar(micPosition) + microView.adapter.notifyDataSetChanged() + //下麦时更新最高最低头饰 + GiftValueMrg.get().updateRoomGiftValue(false) + } + + fun onQueueMicStateChange(micPosition: Int, micPosState: Int) { + microView.adapter.notifyDataSetChanged() + onMicStateChanged() + } + + private fun addOrRemoveMatchPool() { + if (AvRoomDataManager.get().isCpRoom && AvRoomDataManager.get().isRoomOwner) { + if (AvRoomDataManager.get().findFreePosition() > 0) { + AvRoomModel.get().removeIsomerism().subscribe() + } else if ((TextUtils.isEmpty(AvRoomDataManager.get().mCurrentRoomInfo?.limitType) + && TextUtils.isEmpty(AvRoomDataManager.get().mCurrentRoomInfo?.getRoomPwd())) + ) { + AvRoomModel.get().addIsomerism().subscribe() + } + } + } + + override fun kickDownMicroPhoneSuccess() { + updateMicBtn() + toast(R.string.kick_mic) + } + + override fun showOwnerClickDialog( + roomMicInfo: RoomMicInfo, + micPosition: Int, + currentUid: Long + ) { + val buttonItems: MutableList = ArrayList(4) + val presideMic = AvRoomDataManager.get().isDatingMode && micPosition == -1 + val presideText = if (presideMic) "当主持人" else "" + val buttonItem1 = ButtonItem( + getString(R.string.embrace_up_mic) + presideText, + object : ButtonItem.OnClickListener { + override fun onClick() { + RoomInviteActivity.openActivity(activity, micPosition, presideMic) + } + }) + val buttonItem2 = + ButtonItem(if (roomMicInfo.isMicMute) getString(R.string.no_forbid_mic) else getString( + R.string.forbid_mic + ), object : ButtonItem.OnClickListener { + override fun onClick() { + if (roomMicInfo.isMicMute) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS) + return + } + mvpPresenter?.openMicroPhone(micPosition) + } else { + mvpPresenter?.roomOperate(SuperAdminModel.CLOSE_MIC) + mvpPresenter?.closeMicroPhone(micPosition) + } + } + }) + val isQueue = AvRoomDataManager.get().isQueuingMicro + val isBossMic = micPosition == -1 + val unlockStr = + getString(if (isQueue && (!isBossMic)) R.string.unlock_mic_queue else R.string.unlock_mic) + val lockStr = + getString(if (isQueue && (!isBossMic)) R.string.lock_mic_queue else R.string.lock_mic) + val buttonItem3 = ButtonItem( + if (roomMicInfo.isMicLock) unlockStr else lockStr, + ButtonItem.OnClickListener { + if (roomMicInfo.isMicLock()) { + if (SuperAdminUtil.isSuperAdmin()) { + SingleToastUtil.showToast(SaConstant.TOAST_ERROR_TIPS) + return@OnClickListener + } + mvpPresenter?.unLockMicroPhone(micPosition) + } else { + mvpPresenter?.roomOperate(SuperAdminModel.LOCK_MIC) + mvpPresenter?.lockMicroPhone(micPosition) + } + }) + val buttonItem4 = + ButtonItem("上麦", { toUpMicroPhone(micPosition, currentUid.toString() + "", false) }) + //别问为什么,ui调整了顺序 + //禁用超管的上麦和抱TA上麦 + if (!SuperAdminUtil.isSuperAdmin()) { + buttonItems.add(buttonItem4) + if (!AvRoomDataManager.get().isDatingVipMic(micPosition)) { + buttonItems.add(buttonItem1) + } + } + if (!AvRoomDataManager.get().isOpenPKMode) { + //超管只有锁麦操作 + if (SuperAdminUtil.isSuperAdmin()) { + if (!roomMicInfo.isMicLock && !isQueue) { + buttonItems.add(buttonItem3) + } + } else { + if (!AvRoomDataManager.get().isDatingVipMic(micPosition)) { + buttonItems.add(buttonItem3) + } + } + } + //超管只有闭麦操作 + if (SuperAdminUtil.isSuperAdmin()) { + if (!roomMicInfo.isMicMute) { + buttonItems.add(buttonItem2) + } + } else { + buttonItems.add(buttonItem2) + } + dialogManager.showCommonPopupDialog(buttonItems, getString(R.string.cancel)) + } + + override fun chatRoomReConnectView() { + if (microView != null && microView.adapter != null) microView.adapter.notifyDataSetChanged() + } + + override fun onAvatarBtnClick(position: Int) { + val roomInfo = AvRoomDataManager.get().mCurrentRoomInfo + if ((roomInfo != null) && roomInfo.isLeaveMode && (position == -1)) { + showUserCardDialog(roomInfo.uid.toString()) + } else { + val roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByMicPosition(position) + if (roomQueueInfo == null || roomQueueInfo.mChatRoomMember == null) { + return + } + val account = roomQueueInfo.mChatRoomMember.account + if (TextUtils.isEmpty(account)) { + return + } + showUserCardDialog(account) + } + } + + override fun onUpMicBtnClick(position: Int, chatRoomMember: MicMemberInfo?) { + if (AvRoomDataManager.get().isDatingVipMic(position) && !AvRoomDataManager.get() + .isDatingVip(AuthModel.get().currentUid) + ) { + DatingVipRuleDialog.newInstance(mContext).show() + } else { + mvpPresenter?.microPhonePositionClick(position, chatRoomMember) + } + } + + override fun onLockBtnClick(position: Int) { + mvpPresenter?.unLockMicroPhone(position) + } + + override fun onRoomSettingsClick() { + showRoomIntroduction(AvRoomDataManager.get().isRoomOwner || AvRoomDataManager.get().isRoomAdmin) + } + + fun clearDialog() { + giftDialog?.dismiss() + dynamicFaceDialog?.dismiss() + redPackageSendDialog?.dismissAllowingStateLoss() + } + + private fun showRoomIntroduction(isModify: Boolean) { + var isModify = isModify + val info = AvRoomDataManager.get().mCurrentRoomInfo ?: return + if (SuperAdminUtil.isSuperAdmin()) { + isModify = false + } + if (isModify) { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_SET_TOPIC_CLICK, "设置房间话题") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_SET_TOPIC_CLICK, "设置房间话题") + RoomTitleEditActivity.startForResult(activity, info.roomDesc, info.introduction) + } else { + val dialogFragment = + RoomTitleDialogFragment.getInstance(info.roomDesc, info.introduction) + dialogFragment.show(requireActivity().supportFragmentManager, "roomTitle") + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + if (requestCode == 200 && resultCode == 100) { + if (data != null && data.extras != null) { + val account = data.extras?.getString("account") + val nick = data.extras?.getString("nick") + if (TextUtils.isEmpty(account)) return + if (AvRoomDataManager.get().isLeaveMode && + (account == AvRoomDataManager.get().roomUid.toString()) + ) { + showToast(getString(R.string.tips_close_leave_mode_first)) + return + } + val micPosition = data.extras?.getInt(Constants.KEY_POSITION, Int.MIN_VALUE) + if (micPosition == Int.MIN_VALUE) return + + //抱人上麦 + mvpPresenter?.inviteMicroPhone( + BaseInfo(account, nick), + micPosition ?: Int.MIN_VALUE + ) + } + } else if (requestCode == SelectFriendActivity.CODE_REQUEST_TO_SHARE_ROOM && + resultCode == Activity.RESULT_OK + ) { + val targetUid = data?.getStringExtra(SelectFriendActivity.EXTRA_TARGET_UID) + val sessionType = + data?.getIntExtra(SelectFriendActivity.EXTRA_SESSION_TYPE, SessionType.P2P) + ?: SessionType.P2P + IMNetEaseManager.get().sendSharingRoomMessage(sessionType, targetUid) + } + } + + fun onChatRoomMemberBlackAdd(account: String?) { + //拉黑 + if (AvRoomDataManager.get().isOnMic(account)) { + val micPosition = AvRoomDataManager.get().getMicPosition(account) + mvpPresenter?.downMicroPhone(micPosition, true) + } + val memberListIterator = AvRoomDataManager.get().mRoomManagerList.listIterator() + while (memberListIterator.hasNext()) { + if ((memberListIterator.next().account == account)) { + memberListIterator.remove() + } + } + if (AvRoomDataManager.get().isRoomOwner(account)) { + //当前是房主 + AvRoomDataManager.get().mRoomCreateMember = null + } + } + + override fun showToast(msg: String) { + toast(msg) + } + + override fun onSendMsgSuccess() { + inputEdit.setText("") + } + + /** + * 显示资料卡片 + */ + private fun showUserCardDialog(account: String) { + val list = ButtonItemFactory.createCommonButtonItems( + mContext, + JavaUtil.str2long(account), + true, + true, + true, + this@GameRoomFragment + ) + GiftDialog.GIFT_DIALOG_FROM = "房间" + UserInfoDialog(mContext, JavaUtil.str2long(account), list, true).show() + } + + fun dismissGiftDialog() { + if (giftDialog?.isShowing == true) { + giftDialog?.dismiss() + } + } + + @SuppressLint("CheckResult") + override fun toUpMicroPhone(micPosition: Int, currentUid: String, b: Boolean) { + checkPermission(Manifest.permission.RECORD_AUDIO) + .subscribe({ result: Boolean -> + if (result) { + mvpPresenter?.upMicroPhone(micPosition, currentUid, b) + } else { + toast("请给予麦克风权限后再试!") + } + }, { throwable: Throwable? -> toast("发生一些异常,请稍后重试!") }) + } + + /** + * 是否有麦克风权限 + * + * @return + */ + private val isHavingMicPermissions: Boolean + private get() = ContextCompat.checkSelfPermission( + mContext, + Manifest.permission.RECORD_AUDIO + ) == PackageManager.PERMISSION_GRANTED + + override fun noFollow() { + messageView.post { + val roomInfo: RoomInfo? = AvRoomDataManager.get().mCurrentRoomInfo + val userInfo: UserInfo? = UserModel.get().cacheLoginUserInfo + if (roomInfo == null || userInfo == null) { + return@post + } + val roomFollowOwnerAttachment = RoomFollowOwnerAttachment() + roomFollowOwnerAttachment.ownerUid = AvRoomDataManager.get().roomUid + roomFollowOwnerAttachment.userInfo = userInfo + messageView.addMessages( + ChatRoomMessageBuilder.createChatRoomCustomMessage( + roomInfo.roomId.toString(), roomFollowOwnerAttachment + ) + ) + } + } + + override fun noFollow2() { + messageView.post { + val roomInfo: RoomInfo? = AvRoomDataManager.get().mCurrentRoomInfo + val userInfo: UserInfo? = UserModel.get().cacheLoginUserInfo + if (roomInfo == null || userInfo == null) { + return@post + } + val roomFollowOwnerAttachment = RoomFollowOwnerAttachment2() + roomFollowOwnerAttachment.ownerUid = AvRoomDataManager.get().roomUid + roomFollowOwnerAttachment.userInfo = userInfo + messageView.addMessages( + ChatRoomMessageBuilder.createChatRoomCustomMessage( + roomInfo.roomId.toString(), roomFollowOwnerAttachment + ) + ) + } + } + + override fun showMessageHistory(messages: List) { + messageView.addHistoryMessages(messages) + } + + override fun onFollowSuccess(position: Int) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_FOLLOW_OWNER_FROM_ROOM, "语音房-关注房主") + messageView.changeFollowStatus(position, true) + } + + override fun onFollowFail(msg: String) { + toast("关注失败,请稍后重试") + } + + override fun updateMicView() { + gameBinding.microView.adapter.notifyDataSetChanged() + } + + private fun onSendGiftBtnClick() { + if (giftDialog == null) { + GiftDialog.GIFT_DIALOG_FROM = "房间" + giftDialog = GiftDialog(context, 0, true) + giftDialog?.setGiftDialogBtnClickListener(this@GameRoomFragment) + giftDialog?.setOnDismissListener(object : DialogInterface.OnDismissListener { + override fun onDismiss(dialog: DialogInterface) { + giftDialog = null + } + }) + } + if (giftDialog?.isShowing != true && !requireActivity().isFinishing) { + giftDialog?.show() + } + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_GIFT_CLICK, "礼物面板按钮") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_GIFT_CLICK, "礼物面板按钮") + } + + @Subscribe(threadMode = ThreadMode.MAIN) + fun onFirstRechargeEvent(event: FirstChargeEvent) { + FirstChargePrizeDialog( + requireContext(), + event.chargeProdTitle, + event.firstChargeRewardList + ).openDialog() + } + + /** + * 底部按钮点击处理 + */ + private inner class GameRoomBottomViewWrapper : BottomViewListenerWrapper() { + @SuppressLint("CheckResult") + override fun onOpenMicBtnClick() { + val roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByAccount(AuthModel.get().currentUid.toString()) + if (roomQueueInfo?.mRoomMicInfo == null) return + //先判断麦上是否是开麦的 + if (!roomQueueInfo.mRoomMicInfo.isMicMute && !AudioEngineManager.get().isAudienceRole) { + if (!isHavingMicPermissions) { + val rxPermissions = RxPermissions(this@GameRoomFragment) + rxPermissions.request(Manifest.permission.RECORD_AUDIO) + .subscribe { aBoolean: Boolean -> + if (aBoolean) { + AvRoomDataManager.get().mIsNeedOpenMic = false + AudioEngineManager.get().isMute = !AudioEngineManager.get().isMute + AudioEngineManager.get().setRole(Constants.CLIENT_ROLE_BROADCASTER) + updateMicBtn() + } else { + toast("开启权限后才能开麦") + } + } + return + } + val avRoomDataManager = AvRoomDataManager.get() + val tmp = avRoomDataManager.mIsNeedOpenMic + AudioEngineManager.get().isMute = !AudioEngineManager.get().isMute + AvRoomDataManager.get().mIsNeedOpenMic = AudioEngineManager.get().isMute + updateMicBtn() + if (!tmp) { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_CP_ROOM_CLOSE_MIC_CLICK, + "关闭麦克风" + ) + } else { + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_MP_ROOM_CLOSE_MIC_CLICK, + "关闭麦克风" + ) + } + } else if (AvRoomDataManager.get().isOnMic(myUid)) { + AudioEngineManager.get().setRole(Constants.CLIENT_ROLE_BROADCASTER) + } + } + } + + override fun onSendFaceBtnClick() { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_EMOTICON_CLICK, "表情面板按钮") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_EMOTICON_CLICK, "表情面板按钮") + if (AvRoomDataManager.get().isOnMic(myUid) || AvRoomDataManager.get().isRoomOwner) { + if (dynamicFaceDialog == null) { + dynamicFaceDialog = DynamicFaceDialog(context) + dynamicFaceDialog?.setOnDismissListener { dialog: DialogInterface? -> + dynamicFaceDialog = null + } + dynamicFaceDialog?.setFaceFilter { faceInfoList: MutableList -> + //审核中版本过滤表情,显示 + if (MarketVerifyModel.get().isMarketChecking) { + val faceInfoIterator: MutableIterator = + faceInfoList.iterator() + while (faceInfoIterator.hasNext()) { + val faceInfo: FaceInfo = faceInfoIterator.next() + if ((faceInfo.id == 24 + ) || (faceInfo.id == 17 + ) || (faceInfo.id == 40) + ) { + faceInfoIterator.remove() + } + } + return@setFaceFilter faceInfoList + } else { + return@setFaceFilter faceInfoList + } + } + } + if (dynamicFaceDialog?.isShowing != true) { + dynamicFaceDialog?.show() + } + } else { + toast("上麦才能发表情哦!") + } + } + + override fun onSendMsgBtnClick() { + inputLayout.visibility = View.VISIBLE + inputEdit.isFocusableInTouchMode = true + inputEdit.requestFocus() + KeyBoardUtils.showKeyBoard(context, inputEdit) + // + StatisticManager.Instance().onEvent( + BasicConfig.INSTANCE.appContext, + StatisticsProtocol.Event.EVENT_ROOM_INPUT_BOX_CLICK, "底部文字输入框点击", null + ) + } + + override fun onSendGiftBtnClick() { + this@GameRoomFragment.onSendGiftBtnClick() + } + + override fun onRemoteMuteBtnClick() { + val isRemoteMute = !AudioEngineManager.get().isRemoteMute + if (isRemoteMute) { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_CLOSE_SOUND_CLICK, "关闭声音") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_CLOSE_SOUND_CLICK, "关闭声音") + } + AudioEngineManager.get().isRemoteMute = isRemoteMute + updateRemoteMuteBtn() + } + + override fun onMoreBtnClick() { + if (AvRoomDataManager.get().isCpRoom) { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_CP_ROOM_MORE_CLICK, "更多面板按钮") + } else StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_MP_ROOM_MORE_CLICK, "更多面板按钮") + val dialog = RoomOperationDialog(mContext) + dialog.setOnActionListener { + redPackageSendDialog = RedPackageSendDialog() + redPackageSendDialog?.show(activity) + StatisticManager.Instance().onEvent( + StatisticsProtocol.Event.EVENT_ROOM_SENDHONGBAO_CLICK, + "进入发红包页面" + ) + } + dialog.show() + } + + override fun onRoomMessageClick() { + StatisticManager.Instance() + .onEvent(StatisticsProtocol.Event.EVENT_ROOM_MESSAGE_CLICK, "语音房_消息") + RoomMsgActivity.start(mContext) + } + } + + companion object { + @JvmStatic + fun newInstance(isRoomMin: Boolean): GameRoomFragment { + val roomFragment = GameRoomFragment() + val bundle = Bundle() + //是否是最小化进来 + bundle.putBoolean(Constants.IS_ROOM_MIN, isRoomMin) + roomFragment.arguments = bundle + return roomFragment + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java index 013f096be..39d095bb9 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyFragment.java @@ -213,8 +213,13 @@ public class HomePartyFragment extends AbsRoomFragment implements View.OnClickLi @SuppressLint("CheckResult") @Override public void initiate() { - roomFragment = HomePartyRoomFragment.newInstance(isRoomMin); - getChildFragmentManager().beginTransaction().replace(R.id.container, roomFragment).commitAllowingStateLoss(); + roomFragment = GameRoomFragment.newInstance(isRoomMin); + //roomFragment = HomePartyRoomFragment.newInstance(isRoomMin); + + getChildFragmentManager() + .beginTransaction() + .replace(R.id.container, roomFragment) + .commitAllowingStateLoss(); if (!AvRoomDataManager.get().haveSelfChange && AvRoomDataManager.get().mCurrentRoomInfo != null) { AvRoomDataManager.get().mIsNeedGiftEffect = AvRoomDataManager.get().mCurrentRoomInfo.isHasAnimationEffect(); diff --git a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java index 628f561d1..917bb1c9e 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/fragment/HomePartyRoomFragment.java @@ -372,8 +372,6 @@ public class HomePartyRoomFragment extends BaseMvpFragment onRoomSettingsClick()); - microView.findViewById(R.id.ll_ktv_top).setOnClickListener(v -> onRoomSettingsClick()); inputLayout.setOnTouchListener((v, event) -> { inputEdit.clearFocus(); diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/AppConfig.java b/app/src/main/java/com/yizhuan/erban/avroom/game/AppConfig.java new file mode 100644 index 000000000..aa22f9e7f --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/AppConfig.java @@ -0,0 +1,19 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.yizhuan.erban.avroom.game; + +public class AppConfig { + + protected static final String APP_ID = "1467745235064848385"; + protected static final String APP_KEY = "BvjLDpWol7OihaYeFebuepx1bZu6cxU5"; + + protected static boolean isTestEnv = true; + + // 请接入方自己设置 RoomID, 只有在同一房间里,才能一起玩游戏 + protected static final String mRoomID = "9009";//房间ID,同一个房间ID可对战 + protected static final String mLanguage = "zh-CN";//语言 + + protected static final String GET_APP_CODE = "https://fat-mgp-hello.sudden.ltd/login"; +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/GameDelegate.kt b/app/src/main/java/com/yizhuan/erban/avroom/game/GameDelegate.kt new file mode 100644 index 000000000..faf1b24a2 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/GameDelegate.kt @@ -0,0 +1,518 @@ +package com.yizhuan.erban.avroom.game + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.text.TextUtils +import android.util.Log +import android.view.View +import android.view.ViewTreeObserver.OnGlobalLayoutListener +import android.widget.FrameLayout +import com.yizhuan.xchat_android_core.auth.AuthModel +import com.yizhuan.xchat_android_core.room.game.GameModel +import com.yizhuan.xchat_android_core.utils.LogUtils +import com.yizhuan.xchat_android_core.utils.net.RxHelper +import com.yizhuan.xchat_android_library.utils.SingleToastUtil +import okhttp3.* +import org.json.JSONException +import org.json.JSONObject +import tech.sud.mgp.core.* +import java.io.IOException +import java.util.* + +class GameDelegate(val activity: Activity, val container: FrameLayout) { + + companion object { + const val MG_ID_BUMPER_CAR = 1461227817776713818L //游戏ID:碰碰车 + + const val MG_ID_FLY_CUTTER = 1461228379255603251L //游戏ID:飞刀达人 + + const val MG_ID_DRAW_GUESS = 1461228410184400899L //游戏ID:你画我猜 + + const val MG_ID_GO_BANG = 1461297734886621238L //游戏ID:五子棋 + + } + + private val TAG = "GameActivity" + private var APP_CODE = "" + + + private val mRoomID = "9009" //房间ID,同一个房间ID可对战 + + private val mLanguage = "zh-CN" //语言 + + + private val mCurrentSeat = 1 //当前用户需要上几号麦位 + + //调用游戏SDK的接口,成功加载游戏后可用: + private var iSudFSTAPP: ISudFSTAPP? = null + + + //小游戏ID + private var mMGID = MG_ID_BUMPER_CAR + + //通用状态-游戏,关键词 + private var mKeyWord: String? = null + private val mUid = AuthModel.get().currentUid.toString() + + private val loginCallback: AppLoginListener = + object : AppLoginListener { + override fun onLoginFailure(err: String?) { + SingleToastUtil.showToast(err) + } + + override fun onLoginSuccess(new_code: String, expire_Date: Long) { + APP_CODE = new_code + Handler(Looper.getMainLooper()).post { + //初始化游戏SDK + initGameSDK( + activity, + AppConfig.APP_ID, + AppConfig.APP_KEY, + AppConfig.isTestEnv + ) + } + } + + + } + + init { + login(loginCallback) + } + + /** + * "接入方客户端"登陆接口, 从"接入方服务端"获得Code + * "接入方服务端"是通过"服务端接入SDK"获得Code来返回给"接入方客户端"的 + * @param listener + */ + @SuppressLint("CheckResult") + private fun login(listener: AppLoginListener) { + GameModel.getGameCode() + .compose(RxHelper.bindContext(activity)) + .subscribe({ + listener.onLoginSuccess(it.code, it.expireDate) + }, { + listener.onLoginFailure(it.message) + }) + + } + + /** + * 1,初始化游戏SDK + * + * @param context 上下文 + * @param appID appID + * @param appKey appKey + * @param isTestEnv 是否是测试环境,true:测试环境,false:正式环境 + */ + private fun initGameSDK(context: Context, appID: String, appKey: String, isTestEnv: Boolean) { + SudMGP.initSDK(context, appID, appKey, isTestEnv, object : ISudListenerInitSDK { + override fun onSuccess() { + loadMG(activity, mUid, mRoomID, APP_CODE, mMGID, mLanguage) + } + + override fun onFailure(code: Int, errInfo: String) { + showToast("初始化游戏SDK失败:$code--errInfo:$errInfo") + } + }) + + } + + /** + * 2,加载游戏 + * + * @param activity 上下文Activity + * @param userID 用户ID,业务系统保证每个用户拥有唯一ID + * @param roomID 房间ID,进入同一房间内的 + * @param code 令牌 + * @param mgID 小游戏ID + * @param language 游戏语言 现支持,简体:zh-CN 繁体:zh-TW 英语:en-US 马来语:ms-MY + */ + private fun loadMG( + activity: Activity, + userID: String, + roomID: String, + code: String, + mgID: Long, + language: String + ) { + iSudFSTAPP = SudMGP.loadMG(activity, userID, roomID, code, mgID, language, mISudFSMMG) + addGameView(iSudFSTAPP!!.gameView) + } + + /** + * 3,将游戏view添加到我们的布局当中 + * + * @param gameView + */ + private fun addGameView(gameView: View) { + container.addView(gameView) + } + + private fun showToast(content: String) { + SingleToastUtil.showToast(content) + } + + /** + * 例如"你画我猜"游戏的文字命中 + */ + private fun hitTheMark() { + val keyWord = mKeyWord + if (TextUtils.isEmpty(keyWord)) { + return + } + notifySelfTextHit(keyWord) + } + + /** + * 通知"文字命中状态"到游戏端 + * + * @param iSudFSTAPP + * @param keyWord + */ + private fun notifySelfTextHit(keyWord: String?) { + try { + //状态名称 + val state: String = SudMGPAPPState.APP_COMMON_SELF_TEXT_HIT + + //状态数据 + val jsonObject = JSONObject() + jsonObject.put("isHit", true) // true 命中,false 未命中 + jsonObject.put("keyWord", keyWord) // true 命中,false 未命中 + jsonObject.put("text", "我猜这是:$keyWord") // 聊天原始内容,这里的值只是一个示例,意指内容当中包含关键词则命中,具体按业务规则定。 + val dataJson = jsonObject.toString() + + //状态通知回调 + val iSudListenerNotifyStateChange: ISudListenerNotifyStateChange? = null + + //调用接口 + iSudFSTAPP?.notifyStateChange(state, dataJson, iSudListenerNotifyStateChange) + } catch (e: Exception) { + e.printStackTrace() + } + } + + /** + * 设置当前关键词 + * + * @param keyWord + */ + private fun setKeyWord(keyWord: String?) { + mKeyWord = keyWord + } + + /** + * 游戏SDK调用app的接口 + */ + private val mISudFSMMG: ISudFSMMG = object : ISudFSMMG { + + override fun onGameLog(p0: String?) { + LogUtils.d(p0) + } + + override fun onGameStarted() { + } + + override fun onGameDestroyed() { + } + + /** + * 回调此方法,表示令牌过期,此时需要刷新令牌并使用ISudFSMStateHandle回调 + * @param handle + * @param dataJson + */ + override fun onExpireCode(handle: ISudFSMStateHandle, dataJson: String) { + login(object : AppLoginListener { + override fun onLoginFailure(err: String?) { + + } + + override fun onLoginSuccess(new_code: String, expire_Date: Long) { + APP_CODE = new_code + try { + val jsonObject = JSONObject() + jsonObject.put("ret_code", 0) + jsonObject.put("ret_msg", "success") + handle.success(jsonObject.toString()) + } catch (e: JSONException) { + e.printStackTrace() + } + iSudFSTAPP?.updateCode(APP_CODE, null) + } + + }) + } + + /** + * 处理获取游戏视图信息 + * @param handle + * @param dataJson + */ + override fun onGetGameViewInfo(handle: ISudFSMStateHandle, dataJson: String) { + //拿到游戏View的宽高 + val gameViewWidth = container.measuredWidth + val gameViewHeight = container.measuredHeight + if (gameViewWidth > 0 && gameViewHeight > 0) { + notifyGameViewInfo(handle, gameViewWidth, gameViewHeight) + return + } + + //如果游戏View未加载完成,则监听加载完成时回调 + container.viewTreeObserver.addOnGlobalLayoutListener(object : OnGlobalLayoutListener { + override fun onGlobalLayout() { + container.viewTreeObserver.removeOnGlobalLayoutListener(this) + val width = container.measuredWidth + val height = container.measuredHeight + notifyGameViewInfo(handle, width, height) + } + }) + } + + override fun onGetGameCfg(p0: ISudFSMStateHandle?, p1: String?) { + + } + + /** + * 通知游戏,游戏视图信息 + * @param handle + * @param gameViewWidth + * @param gameViewHeight + */ + private fun notifyGameViewInfo( + handle: ISudFSMStateHandle, + gameViewWidth: Int, + gameViewHeight: Int + ) { + try { + val jsonObject = JSONObject() + jsonObject.put("ret_code", 0) + jsonObject.put("ret_msg", "success") + + //游戏View大小 + val viewSize = JSONObject() + viewSize.put("width", gameViewWidth) + viewSize.put("height", gameViewHeight) + jsonObject.put("view_size", viewSize) + + //游戏安全操作区域 + val viewGameRect = JSONObject() + viewGameRect.put("left", 0) + viewGameRect.put("top", 600) + viewGameRect.put("right", 0) + viewGameRect.put("bottom", 600) + jsonObject.put("view_game_rect", viewGameRect) + + //通知游戏 + val json = jsonObject.toString() + Log.d(TAG, "notifyGameViewInfo:$json") + handle.success(json) + } catch (e: JSONException) { + e.printStackTrace() + } + } + + /** + * 游戏状态变化 + * @param handle + * @param state 状态名 + * @param dataJson 状态数据,json字符串 + */ + override fun onGameStateChange( + handle: ISudFSMStateHandle, + state: String, + dataJson: String + ) { + Log.d(TAG, "onGameStateChange state:$state--dataJson:$dataJson") + when (state) { + SudMGPMGState.MG_COMMON_PUBLIC_MESSAGE -> showToast("游戏:公屏消息") + SudMGPMGState.MG_COMMON_KEY_WORD_TO_HIT -> { + showToast("游戏:关键词状态") + if (TextUtils.isEmpty(dataJson)) { + setKeyWord(null) + } else { + try { + val jsonObject = JSONObject(dataJson) + if (jsonObject.isNull("word")) { + setKeyWord(null) + } else { + val keyWord = jsonObject.getString("word") + setKeyWord(keyWord) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + } + } + } + + /** + * 玩家状态变化 + * @param handle + * @param userId 玩家用户ID + * @param state 状态名 + * @param dataJson 状态数据,json字符串。参考文档 + */ + override fun onPlayerStateChange( + handle: ISudFSMStateHandle, + userId: String, + state: String, + dataJson: String + ) { + Log.d(TAG, "onPlayerStateChange userId:$userId--state:$state--dataJson:$dataJson") + when (state) { + SudMGPMGState.MG_COMMON_PLAYER_IN -> handlePlayerIn(userId, dataJson) + SudMGPMGState.MG_COMMON_PLAYER_READY -> handlePlayerReady(userId, dataJson) + SudMGPMGState.MG_COMMON_PLAYER_CAPTAIN -> handlePlayerCaptain(userId, dataJson) + SudMGPMGState.MG_COMMON_PLAYER_PLAYING -> handlePlayerPlaying(userId, dataJson) + } + } + } + + private fun handlePlayerIn(userId: String, dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + val isIn = jsonObject.getBoolean("isIn") + if (retCode != 0) { + if (retCode == 100201) { + showToast("100201: 战斗时房间不能加入") + } else { + showToast("mg_common_player_in 状态失败, 错误码:$retCode") + } + return + } + if (isIn) { // 已加入 + var teamId = 0 + if (jsonObject.has("teamId")) { + teamId = jsonObject.getInt("teamId") + } + showToast("加入游戏分组:$teamId") + } else { // 未加入 + var reason = 0 + if (jsonObject.has("reason")) { + reason = jsonObject.getInt("reason") + } + if (reason == 0) { + showToast("主动退出游戏") + } else if (reason == 1) { + val userid = jsonObject.getString("kickUID") + showToast(userid + "将我踢出游戏") + } + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handlePlayerReady(userId: String, dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + val isReady = jsonObject.getBoolean("isReady") + if (retCode != 0) { + showToast("mg_common_player_ready 操作失败, 错误码:$retCode") + return + } + if (isReady) { // 已准备 + + } else { // 未准备 + + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handlePlayerCaptain(userId: String, dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + val isCaptain = jsonObject.getBoolean("isCaptain") + if (retCode != 0) { + showToast("mg_common_player_captain 操作失败, 错误码:$retCode") + return + } + + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun handlePlayerPlaying(userId: String, dataJson: String) { + try { + val jsonObject = JSONObject(dataJson) + val retCode = jsonObject.getInt("retCode") + if (retCode != 0) { + if (retCode == 100503) { + showToast("100503: 有人未准备") + } else if (retCode == 100504) { + showToast("100504: 开始游戏的人数不足") + } else { + showToast("mg_common_player_playing 操作失败, 错误码:$retCode") + } + return + } + val isPlaying = jsonObject.getBoolean("isPlaying") + if (!isPlaying) { // 未在游戏中 + var reason = 0 + if (jsonObject.has("reason")) { + reason = jsonObject.getInt("reason") + } + + if (reason == 0) { + showToast("正常结束") + } else if (reason == 1) { + showToast("提前结束(自己不玩了)") + } else if (reason == 2) { + showToast("无真人可以提前结束(无真人,只有机器人)") + } else if (reason == 3) { + showToast("所有人都提前结束") + } else { + showToast("未在游戏中, reason = $reason") + } + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + + fun onStart() { + iSudFSTAPP?.startMG() //启动游戏 + } + + fun onResume() { + iSudFSTAPP?.playMG() //开始游戏 + } + + fun onPause() { + iSudFSTAPP?.pauseMG() //暂停游戏 + } + + fun onStop() { + iSudFSTAPP?.stopMG() //停止游戏 + } + + fun onDestroy() { + iSudFSTAPP?.destroyMG() + } + +} + +internal interface AppLoginListener { + /** + * App Server 登陆失败, App Server 不能返回CODE + */ + fun onLoginFailure(err: String?) + + /** + * App Server 登陆成功, App Server调用服务端接入SDK的API获取Code 返回给 App + * App 就要用CODE和自己生成的UserID去调用SDK的初始化函数,登陆小游戏 + * 小游戏登陆成功后,其UserID,就是App传的UserID + */ + fun onLoginSuccess(new_code: String, expire_Date: Long) +} \ No newline at end of file diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPAPPState.java b/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPAPPState.java new file mode 100644 index 000000000..477598de1 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPAPPState.java @@ -0,0 +1,82 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.yizhuan.erban.avroom.game; + +/** + * Time:2021/10/19 + * Description: APP to MG 的状态定义 + */ +public class SudMGPAPPState { + + // region 通用状态 + + /** + * 加入状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_IN = "app_common_self_in"; + + /** + * 准备状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_READY = "app_common_self_ready"; + + /** + * 游戏状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_PLAYING = "app_common_self_playing"; + + /** + * 队长状态 + * 最低版本: v1.1.30.xx + */ + public static final String APP_COMMON_SELF_CAPTAIN = "app_common_self_captain"; + + /** + * 踢人 + * v1.1.30.xx + */ + public static final String APP_COMMON_SELF_KICK = "app_common_self_kick"; + + /** + * 结束游戏 + * v1.1.30.xx + */ + public static final String APP_COMMON_SELF_END = "app_common_self_end"; + + /** + * 房间状态, (depreated 已废弃v1.1.30.xx) + */ + public static final String APP_COMMON_SELF_ROOM = "app_common_self_room"; + + /** + * 麦位状态, (depreated 已废弃v1.1.30.xx) + */ + public static final String APP_COMMON_SELF_SEAT = "app_common_self_seat"; + + /** + * 麦克风状态 + */ + public static final String APP_COMMON_SELF_MICROPHONE = "app_common_self_microphone"; + + /** + * 文字命中状态 + */ + public static final String APP_COMMON_SELF_TEXT_HIT = "app_common_self_text_hit"; + + // endregion 通用状态 + + // region 碰碰我最强 + // endregion 碰碰我最强 + + // region 飞刀达人 + // endregion 飞刀达人 + + // region 你画我猜 + // endregion 你画我猜 + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPMGState.java b/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPMGState.java new file mode 100644 index 000000000..a9651bd06 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/game/SudMGPMGState.java @@ -0,0 +1,93 @@ +/* + Copyright © Sud.Tech + https://sud.tech + */ +package com.yizhuan.erban.avroom.game; + +/** + * Time:2021/10/19 + * Description: MG to APP 的状态定义 + */ +public class SudMGPMGState { + + // region 通用状态-游戏 + + /** + * 公屏消息 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PUBLIC_MESSAGE = "mg_common_public_message"; + + /** + * 关键词状态 + */ + public static final String MG_COMMON_KEY_WORD_TO_HIT = "mg_common_key_word_to_hit"; + + // endregion 通用状态-游戏 + + + // region 通用状态-玩家 + + /** + * 加入状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_IN = "mg_common_player_in"; + + /** + * 准备状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_READY = "mg_common_player_ready"; + + /** + * 队长状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_CAPTAIN = "mg_common_player_captain"; + + /** + * 游戏状态 (已修改) + * 最低版本: v1.1.30.xx + */ + public static final String MG_COMMON_PLAYER_PLAYING = "mg_common_player_playing"; + + // endregion 通用状态-玩家 + + + // region 碰碰我最强 + // endregion 碰碰我最强 + + // region 飞刀达人 + // endregion 飞刀达人 + + // region 你画我猜 + + /** + * 选词中 + */ + public static final String MG_DG_SELECTING = "mg_dg_selecting"; + + /** + * 作画中 + */ + public static final String MG_DG_PAINTING = "mg_dg_painting"; + + /** + * 错误答案 + */ + public static final String MG_DG_ERRORANSWER = "mg_dg_erroranswer"; + + /** + * 总积分 + */ + public static final String MG_DG_TOTALSCORE = "mg_dg_totalscore"; + + /** + * 本次积分 + */ + public static final String MG_DG_SCORE = "mg_dg_score"; + + // endregion 你画我猜 + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/presenter/GameRoomPresenter.java b/app/src/main/java/com/yizhuan/erban/avroom/presenter/GameRoomPresenter.java new file mode 100644 index 000000000..d47080f3b --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/presenter/GameRoomPresenter.java @@ -0,0 +1,598 @@ +package com.yizhuan.erban.avroom.presenter; + +import android.annotation.SuppressLint; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.netease.nimlib.sdk.NIMClient; +import com.netease.nimlib.sdk.RequestCallbackWrapper; +import com.netease.nimlib.sdk.ResponseCode; +import com.netease.nimlib.sdk.chatroom.ChatRoomMessageBuilder; +import com.netease.nimlib.sdk.chatroom.ChatRoomService; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.netease.nimlib.sdk.msg.constant.MsgTypeEnum; +import com.netease.nimlib.sdk.msg.model.QueryDirectionEnum; +import com.netease.nimlib.sdk.util.Entry; +import com.orhanobut.logger.Logger; +import com.yizhuan.erban.avroom.view.IGameRoomView; +import com.yizhuan.erban.base.BaseMvpPresenter; +import com.yizhuan.xchat_android_core.Constants; +import com.yizhuan.xchat_android_core.auth.AuthModel; +import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; +import com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; +import com.yizhuan.xchat_android_core.im.custom.bean.RoomInfoAttachment; +import com.yizhuan.xchat_android_core.initial.InitialModel; +import com.yizhuan.xchat_android_core.initial.bean.InitInfo; +import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; +import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; +import com.yizhuan.xchat_android_core.pay.bean.WalletInfo; +import com.yizhuan.xchat_android_core.praise.PraiseModel; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_core.room.exception.AntiSpamHitException; +import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; +import com.yizhuan.xchat_android_core.room.giftvalue.helper.GiftValueMrg; +import com.yizhuan.xchat_android_core.room.model.AvRoomModel; +import com.yizhuan.xchat_android_core.room.model.HomePartyModel; +import com.yizhuan.xchat_android_core.room.model.RoomBaseModel; +import com.yizhuan.xchat_android_core.room.queue.bean.MicMemberInfo; +import com.yizhuan.xchat_android_core.super_admin.model.SuperAdminModel; +import com.yizhuan.xchat_android_core.super_admin.util.SuperAdminUtil; +import com.yizhuan.xchat_android_core.user.UserModel; +import com.yizhuan.xchat_android_core.user.bean.BaseInfo; +import com.yizhuan.xchat_android_core.user.bean.UserInfo; +import com.yizhuan.xchat_android_core.utils.net.DontWarnObserver; +import com.yizhuan.xchat_android_core.utils.net.RxHelper; +import com.yizhuan.xchat_android_library.base.PresenterEvent; +import com.yizhuan.xchat_android_library.net.rxnet.callback.CallBack; +import com.yizhuan.xchat_android_library.utils.ListUtils; +import com.yizhuan.xchat_android_library.utils.SingleToastUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.SingleSource; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.functions.BiConsumer; +import io.reactivex.functions.Consumer; +import io.reactivex.functions.Function; + + +/** + *

+ * + * @author jiahui + * @date 2017/12/8 + */ +public class GameRoomPresenter extends BaseMvpPresenter { + + /** + * 显示关注房主的时间 + */ + public static final int SHOW_FOLLOW_TIME = 3 * 60 * 1000; + + private final HomePartyModel mHomePartyMode; + private final AvRoomModel mAvRoomModel; + private final SuperAdminModel mSuperAdminModel; + protected WalletInfo walletInfo; + /** + * 判断所坑服务端是否响应回来了 + */ + private boolean mIsLockMicPosResultSuccess = true; + private boolean mIsUnLockMicPosResultSuccess = true; + + private Gson gson = new Gson(); + + public GameRoomPresenter() { + mHomePartyMode = new HomePartyModel(); + mAvRoomModel = AvRoomModel.get(); + mSuperAdminModel = new SuperAdminModel(); + } + + /** + * 麦坑点击处理,麦上没人的时候 + * + * @param micPosition 麦序位置 + * @param chatRoomMember 坑上的用户 + */ + public void microPhonePositionClick(final int micPosition, MicMemberInfo chatRoomMember) { + final RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(AuthModel.get().getCurrentUid()); + if (AvRoomDataManager.get().isRoomOwner(currentUid) || AvRoomDataManager.get().isRoomAdmin(currentUid) + || SuperAdminUtil.isSuperAdmin()) { + if (AvRoomDataManager.get().isRoomOwner(currentUid) && currentRoom.isLeaveMode()) { + SingleToastUtil.showToast("请先关闭离开模式"); + return; + } + onOwnerUpMicroClick(micPosition, Long.parseLong(currentUid)); + } else { + if (AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(micPosition).mRoomMicInfo.isMicLock()) { + if (AvRoomDataManager.get().isQueuingMicro()) { + String msg; + if (AvRoomDataManager.get().isOnMic(AuthModel.get().getCurrentUid())) { + msg = "你已经在麦上啦"; + } else { + msg = "要排麦才可以上麦哦~"; + } + SingleToastUtil.showToast(msg); + } + return; + } + if (AvRoomDataManager.get().isQueuingMicro() && AvRoomDataManager.get().myIsInQueue) { + SingleToastUtil.showToast("取消报名才可以上麦哦!"); + return; + } + getMvpView().toUpMicroPhone(micPosition, currentUid, false); + + } + } + + private void onOwnerUpMicroClick(final int micPosition, final long currentUid) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().getRoomQueueMemberInfoByMicPosition(micPosition); + if (roomQueueInfo == null) return; + if (getMvpView() != null) + getMvpView().showOwnerClickDialog(roomQueueInfo.mRoomMicInfo, micPosition, currentUid); + } + + public void lockMicroPhone(int micPosition) { + if (!mIsLockMicPosResultSuccess) { + return; + } + mIsLockMicPosResultSuccess = false; + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(currentRoom.getUid()); + mHomePartyMode.lockMicroPhone(micPosition, currentUid, AuthModel.get().getTicket()) + .doOnSuccess(data -> { + Logger.i("用户%1$s锁坑成功: %2$s", String.valueOf(currentUid), data); + mIsLockMicPosResultSuccess = true; + }) + .doOnError(throwable -> { + Logger.i("用户%1$s锁坑失败: %2$s", String.valueOf(currentUid), + RxHelper.getNotEmptyError(throwable)); + mIsLockMicPosResultSuccess = true; + }) + .subscribe(); + } + + /** + * 坑位释放锁 + */ + public void unLockMicroPhone(int micPosition) { + if (!mIsUnLockMicPosResultSuccess) { + return; + } + mIsUnLockMicPosResultSuccess = false; + RoomInfo currentRoom = AvRoomDataManager.get().mCurrentRoomInfo; + if (currentRoom == null) { + return; + } + final String currentUid = String.valueOf(currentRoom.getUid()); + if (AvRoomDataManager.get().isRoomAdmin() || AvRoomDataManager.get().isRoomOwner(currentUid)) { + mHomePartyMode.unLockMicroPhone(micPosition, currentUid, AuthModel.get().getTicket()) + .subscribe(new Consumer() { + @Override + public void accept(String data) throws Exception { + Logger.i("用户%1$s解麦成功: %2$s", String.valueOf(currentUid), data); + mIsUnLockMicPosResultSuccess = true; + } + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + Logger.i("用户%1$s解麦失败: %2$s", String.valueOf(currentUid), throwable.getMessage()); + mIsUnLockMicPosResultSuccess = true; + } + }); + } + } + + /** + * 下麦 + * + * @param micPosition + * @param isKick 是否是主动的 + */ + public void downMicroPhone(int micPosition, final boolean isKick) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + final String currentUid = String.valueOf(AuthModel.get()); + mHomePartyMode.downMicroPhone(micPosition, new CallBack() { + @Override + public void onSuccess(String data) { + Logger.i("用户%1$s下麦成功:%2$s", currentUid, data); + if (!isKick) { + //被踢了 + if (getMvpView() != null) { + getMvpView().kickDownMicroPhoneSuccess(); + } + } + } + + @Override + public void onFail(int code, String error) { + Logger.i("用户%1$s下麦失败:%2$s----", currentUid, error); + } + }); + } + + /** + * 上麦 + * + * @param micPosition + * @param uId + * @param isInviteUpMic 是否是主动的,false:主动 + * @param isReconnect 是否需要清除礼物值,普通情况下上麦传false,断网重连传ture + */ + public void upMicroPhone(final int micPosition, final String uId, boolean isInviteUpMic, boolean isReconnect) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + if (!isInviteUpMic) { + upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo, isReconnect); + } else { + AvRoomDataManager.get().haveStartDragon = false; + upMicroPhone(micPosition, uId, isInviteUpMic, roomInfo, isReconnect); + } + } + + public void upMicroPhone(final int micPosition, final String uId, boolean isInviteUpMic) { + upMicroPhone(micPosition, uId, isInviteUpMic, false); + } + + public void upMicroPhone(int micPosition, String uId, boolean isInviteUpMic, RoomInfo roomInfo, + boolean isReconnect) { + mHomePartyMode.upMicroPhone(micPosition, uId, String.valueOf(roomInfo.getRoomId()), + isInviteUpMic, new CallBack() { + @Override + public void onSuccess(String data) { + Logger.i("用户%1$s上麦成功:%2$s", uId, data); + if (!isReconnect) { + GiftValueMrg.get().requestUpMic(micPosition, uId); + } else { + GiftValueMrg.get().handleReconnect(true); + } + } + + @Override + public void onFail(int code, String error) { + if (code == RoomBaseModel.CODE_UPDATE_MIC) { + if (getMvpView() != null) { + getMvpView().updateMicView(); + } + } + Logger.i("用户%1$s上麦失败:%2$s----", uId, error); + } + }); + } + + /** + * 邀请用户上麦 + * + * @param micInfo 要邀请的用户 + * @param position 坑位 + */ + public void inviteMicroPhone(final BaseInfo micInfo, final int position) { + final long micUid = micInfo.getUid(); + if (AvRoomDataManager.get().isOnMic(micUid)) { + return; + } + //如果点击的就是自己,那这里就是自己上麦 + if (AvRoomDataManager.get().isOwner(micUid)) { + upMicroPhone(position, String.valueOf(micUid), true); + return; + } + mHomePartyMode.inviteMicroPhone(micInfo, position) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .subscribe(new BiConsumer() { + @Override + public void accept(ChatRoomMessage chatRoomMessage, + Throwable throwable) throws Exception { + if (throwable != null) { + Logger.i("邀请用户%d上麦失败!!!" + micUid); + } else + Logger.i("邀请用户%d上麦成功!!!" + micUid); + } + }); + } + + + /** + * 开麦 + * + * @param micPosition + */ + public void openMicroPhone(int micPosition) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + mHomePartyMode.openMicroPhone(micPosition, roomInfo.getUid()) + .subscribe(new DontWarnObserver() { + @Override + public void accept(String data, String error) { + super.accept(data, error); + if (error != null) { + Logger.i("用户%1$s开麦失败: %2$s", String.valueOf(roomInfo.getUid()), error); + } else { + Logger.i("用户%1$s开麦成功: %2$s", String.valueOf(roomInfo.getUid()), data); + } + } + }); + } + + /** + * 闭麦 + * + * @param micPosition + */ + public void closeMicroPhone(int micPosition) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) { + return; + } + mHomePartyMode.closeMicroPhone(micPosition, roomInfo.getUid()) + .doOnSuccess(data -> { + Logger.i("用户%1$s闭麦成功: %2$s", String.valueOf(roomInfo.getUid()), data); + }) + .doOnError(throwable -> { + Logger.i("用户%1$s闭麦失败: %2$s", String.valueOf(roomInfo.getUid()), + RxHelper.getNotEmptyError(throwable)); + }) + .subscribe(); + } + + public void roomOperate(int operate) { + mSuperAdminModel.roomOperate(operate) + .subscribe(); + } + + /*** + * 发送房间消息 + * @param message + */ + @SuppressLint("CheckResult") + public void sendTextMsg(String message) { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null || TextUtils.isEmpty(message)) return; + IMNetEaseManager.get().sendTextMsg(roomInfo.getRoomId(), message) + .subscribe(new BiConsumer() { + @Override + public void accept(ChatRoomMessage chatRoomMessage, + Throwable throwable) throws Exception { + if (throwable != null) { + if (throwable instanceof AntiSpamHitException) { + Log.e("sendTextMsg", throwable.getMessage()); + } else { + Logger.i("发送房间信息失败:" + throwable.getMessage()); + } + } else { + getMvpView().onSendMsgSuccess(); + IMNetEaseManager.get().addMessagesImmediately(chatRoomMessage); + Logger.i("发送房间信息成功:" + chatRoomMessage.getUuid()); + } + } + }); + } + + @SuppressLint("CheckResult") + public void chatRoomReConnect(final RoomQueueInfo queueInfo) { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + mHomePartyMode.queryRoomMicInfo(String.valueOf(roomInfo.getRoomId())) + .delay(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(entries -> { + if (!ListUtils.isListEmpty(entries)) { + JsonParser jsonParser = new JsonParser(); + MicMemberInfo chatRoomMember; + for (Entry entry : entries) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get().mMicQueueMemberMap.get(Integer.parseInt(entry.key)); + if (roomQueueInfo != null) { + JsonObject valueJsonObj = jsonParser.parse(entry.value).getAsJsonObject(); + if (valueJsonObj != null) { + chatRoomMember = gson.fromJson(valueJsonObj, MicMemberInfo.class); + roomQueueInfo.mChatRoomMember = chatRoomMember; + } + AvRoomDataManager.get().addRoomQueueInfo(entry.key, roomQueueInfo); + } + } + } else { + //麦上都没有人 + AvRoomDataManager.get().resetMicMembers(); + } + if (getMvpView() != null) + getMvpView().chatRoomReConnectView(); + //之前在麦上 + if (queueInfo != null && queueInfo.mChatRoomMember != null && queueInfo.mRoomMicInfo != null) { + RoomQueueInfo roomQueueInfo = AvRoomDataManager.get() + .getRoomQueueMemberInfoByMicPosition(queueInfo.mRoomMicInfo.getPosition()); + //麦上没人 + String account = queueInfo.mChatRoomMember.getAccount(); + if (roomQueueInfo != null && (roomQueueInfo.mChatRoomMember == null || + Objects.equals(account, roomQueueInfo.mChatRoomMember.getAccount()))) { + roomQueueInfo.mChatRoomMember = null; + //断网重连,不要清除麦上的礼物值 + upMicroPhone(queueInfo.mRoomMicInfo.getPosition(), account, true, true); + } + } + IMNetEaseManager.get().mCacheRoomQueueInfo = null; + Logger.i("断网重连获取队列信息成功...." + entries); + }, new Consumer() { + @Override + public void accept(Throwable throwable) throws Exception { + throwable.printStackTrace(); + Logger.i("断网重连获取队列信息失败...."); + } + }); + } + + public void userRoomIn() { + final RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + if (roomInfo == null) return; + long currentUid = AuthModel.get().getCurrentUid(); + mAvRoomModel.userRoomIn(String.valueOf(currentUid), roomInfo.getUid(), 0, "") + .delay(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()).subscribe(); + } + + @NonNull + private ChatRoomMessage getChatRoomMessage(RoomInfo roomInfo, List integers, int second) { + UserInfo userInfo = UserModel.get().getCacheLoginUserInfo(); + List faceReceiveInfos = new ArrayList<>(); + FaceReceiveInfo faceReceiveInfo = new FaceReceiveInfo(); + faceReceiveInfo.setNick(userInfo.getNick()); + faceReceiveInfo.setFaceId(Constants.DRAGON_BAR_ID); + faceReceiveInfo.setUid(userInfo.getUid()); + + faceReceiveInfo.setResultIndexes(integers); + faceReceiveInfos.add(faceReceiveInfo); + + // 发送云信信息给所有人 + FaceAttachment faceAttachment = + new FaceAttachment(CustomAttachment.CUSTOM_MSG_DRAGON_BAR, second); + faceAttachment.setUid(userInfo.getUid()); + faceAttachment.setFaceReceiveInfos(faceReceiveInfos); + + return ChatRoomMessageBuilder.createChatRoomCustomMessage( + // 聊天室id + roomInfo.getRoomId() + "", + // 自定义消息 + faceAttachment + ); + } + + public void updateScreen(boolean isCloseScreen) { + String contentText; + if (isCloseScreen) { + ChatRoomMessage firstMsg = IMNetEaseManager.get().getFirstMessageContent(); + IMNetEaseManager.get().addCloseScreenMessages(firstMsg); + if (AvRoomDataManager.get().closeScreenBySAdmin()) { + contentText = "系统检测涉嫌违规,予以关闭公屏消息警告"; + } else { + contentText = "管理员已关闭聊天公屏"; + } + } else { + contentText = "管理员已开启聊天公屏"; + } + RoomInfoAttachment attachment = new RoomInfoAttachment(CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO, + CustomAttachment.CUSTOM_MSG_UPDATE_ROOM_INFO_CLOSE_SCREEN); + ChatRoomMessage screenMsg = ChatRoomMessageBuilder.createChatRoomCustomMessage( + String.valueOf(AvRoomDataManager.get().getRoomId()), + attachment + ); + screenMsg.setContent(contentText); + IMNetEaseManager.get().addCloseScreenMessages(screenMsg); + } + + + /** + * 检查是否关注了这个用户 + * + * @param uid + */ + @SuppressLint("CheckResult") + public void checkFollow(long uid) { + Single.just("") + .delay(SHOW_FOLLOW_TIME, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .flatMap(new Function>() { + @Override + public SingleSource apply(String s) throws Exception { + return PraiseModel.get().isPraised(AuthModel.get().getCurrentUid(), uid); + } + }) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .compose(RxHelper.handleSchAndExce()) + .subscribe(new BiConsumer() { + @Override + public void accept(Boolean aBoolean, Throwable throwable) throws Exception { + if (throwable != null || getMvpView() == null) { + return; + } + //如果没有关注 + if (!aBoolean) { + getMvpView().noFollow(); + } + } + }); + Observable.interval(1, 5, TimeUnit.MINUTES) + .compose(bindUntilEvent(PresenterEvent.DESTROY)) + .map(aLong -> AvRoomDataManager.get().isRoomFans) + .takeUntil(aBoolean -> aBoolean) + .subscribe(aBoolean -> { + if (!aBoolean && getMvpView() != null) { + getMvpView().noFollow2(); + } + }); + } + + /** + * 公屏历史消息 + */ + public void loadMessageHistory() { + RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; + + if (roomInfo == null) return; + if (!roomInfo.isCloseScreen()) { + int count = 10; + InitInfo initInfo = InitialModel.get().getCacheInitInfo(); + if (initInfo != null) count = initInfo.getRoomMessageCount(); + NIMClient.getService(ChatRoomService.class) + .pullMessageHistoryExType(String.valueOf(roomInfo.getRoomId()), 0, + count, QueryDirectionEnum.QUERY_OLD, new MsgTypeEnum[]{MsgTypeEnum.text}) + .setCallback(new RequestCallbackWrapper>() { + @Override + public void onResult(int code, List result, Throwable exception) { + if (code == ResponseCode.RES_SUCCESS && result != null && result.size() > 0) { + Collections.reverse(result); + if (getMvpView() != null) { + getMvpView().showMessageHistory(result); + } + } + } + }); + } + } + + /** + * 关注房主 + * + * @param position + * @param ownerUid + */ + @SuppressLint("CheckResult") + public void followOwner(int position, long ownerUid) { + PraiseModel.get().praise(ownerUid, true).subscribe(new BiConsumer() { + @Override + public void accept(String s, Throwable throwable) throws Exception { + if (getMvpView() == null) { + return; + } + if (throwable == null) { + getMvpView().onFollowSuccess(position); + } else { + getMvpView().onFollowFail(throwable.getMessage()); + } + } + }); + } + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/view/IGameRoomView.java b/app/src/main/java/com/yizhuan/erban/avroom/view/IGameRoomView.java new file mode 100644 index 000000000..9e7bfd005 --- /dev/null +++ b/app/src/main/java/com/yizhuan/erban/avroom/view/IGameRoomView.java @@ -0,0 +1,83 @@ +package com.yizhuan.erban.avroom.view; + +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMember; +import com.netease.nimlib.sdk.chatroom.model.ChatRoomMessage; +import com.yizhuan.erban.avroom.widget.ViewItem; +import com.yizhuan.xchat_android_core.bean.RoomMicInfo; +import com.yizhuan.xchat_android_core.miniworld.bean.MiniWorldInWorldInfo; +import com.yizhuan.xchat_android_core.room.bean.RoomInfo; +import com.yizhuan.xchat_android_library.base.IMvpBaseView; + +import java.util.List; + +/** + *

轰趴房View层

+ * + * @author jiahui + * @date 2017/12/8 + */ +public interface IGameRoomView extends IMvpBaseView { + + /** + * 被踢下麦成功 + */ + void kickDownMicroPhoneSuccess(); + + /** + * 麦上没人点击坑位处理 + * + * @param roomMicInfo 坑位信息 + * @param micPosition + * @param currentUid + */ + void showOwnerClickDialog(RoomMicInfo roomMicInfo, int micPosition, long currentUid); + + /** + * 断网重连回调 + */ + void chatRoomReConnectView(); + + + void showToast(String msg); + + void onSendMsgSuccess(); + + /** + * 上麦请求 + * + * @param micPosition + * @param currentUid + * @param b + */ + void toUpMicroPhone(int micPosition, String currentUid, boolean b); + + /** + * 没有关注用户的监听 + */ + void noFollow(); + + /** + * 鬼知道之前有一个,现在又要加一个 + */ + void noFollow2(); + + /** + * 没有关注用户的监听 + */ + void showMessageHistory(List messages); + + /** + * 关注成功 + * @param position + */ + void onFollowSuccess(int position); + + /** + * 关注失败 + * @param msg + */ + void onFollowFail(String msg); + + void updateMicView(); + +} diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java index 71364d9ec..990ef0902 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/MessageView.java @@ -11,7 +11,6 @@ import android.text.Spanned; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.text.style.ForegroundColorSpan; -import android.text.style.UnderlineSpan; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; @@ -161,7 +160,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.functions.Function; -import lombok.Setter; import static com.yizhuan.xchat_android_core.im.custom.bean.CustomAttachment.CUSTOM_MSG_RED_PACKAGE; import static com.yizhuan.xchat_android_core.redpackage.RedPackageTypeKt.ALL_DIAMOND; @@ -202,11 +200,17 @@ public class MessageView extends FrameLayout { private int expLevelHeight; private int giftLength; private volatile boolean needAutoScroll = true;//是否自动滚动到底部 - @Setter private Consumer clickConsumer; - @Setter private OnClick onClick; + public void setClickConsumer(Consumer clickConsumer) { + this.clickConsumer = clickConsumer; + } + + public void setOnClick(OnClick onClick) { + this.onClick = onClick; + } + public MessageView(Context context) { this(context, null); } diff --git a/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java b/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java index 5f23f9964..461984757 100644 --- a/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java +++ b/app/src/main/java/com/yizhuan/erban/avroom/widget/MicroView.java @@ -5,42 +5,32 @@ import android.content.Context; import android.graphics.Point; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; -import android.text.TextUtils; import android.util.AttributeSet; import android.util.SparseArray; import android.view.View; -import android.view.ViewGroup; +import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.RelativeLayout; -import androidx.databinding.DataBindingUtil; import androidx.recyclerview.widget.RecyclerView; import com.yizhuan.erban.R; import com.yizhuan.erban.avroom.adapter.BaseMicroViewAdapter; import com.yizhuan.erban.avroom.adapter.CpMicroViewAdapter; import com.yizhuan.erban.avroom.adapter.DatingMicroViewAdapter; -import com.yizhuan.erban.avroom.adapter.KtvMicroViewAdapter; import com.yizhuan.erban.avroom.adapter.MicroViewAdapter; import com.yizhuan.erban.avroom.adapter.OnMicroItemClickListener; -import com.yizhuan.erban.avroom.ktv.KtvView; -import com.yizhuan.erban.databinding.LayoutMicroViewBinding; import com.yizhuan.erban.ui.anim.AnimFactory; import com.yizhuan.erban.ui.widget.magicindicator.buildins.UIUtil; import com.yizhuan.erban.ui.widget.recyclerview.decoration.DatingItemDecoration; -import com.yizhuan.erban.utils.RegexUtil; import com.yizhuan.xchat_android_core.bean.RoomQueueInfo; import com.yizhuan.xchat_android_core.im.custom.bean.FaceAttachment; import com.yizhuan.xchat_android_core.manager.AvRoomDataManager; import com.yizhuan.xchat_android_core.manager.IMNetEaseManager; import com.yizhuan.xchat_android_core.manager.RoomEvent; -import com.yizhuan.xchat_android_core.manager.AudioEngineManager; import com.yizhuan.xchat_android_core.noble.NobleResourceType; import com.yizhuan.xchat_android_core.noble.NobleUtil; -import com.yizhuan.xchat_android_core.room.bean.RoomInfo; import com.yizhuan.xchat_android_core.room.event.ReceiveFaceEvent; import com.yizhuan.xchat_android_core.room.face.FaceReceiveInfo; -import com.yizhuan.xchat_android_library.utils.config.BasicConfig; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -56,23 +46,17 @@ import io.reactivex.disposables.Disposable; * @author xiaoyu * @date 2017/12/20 */ -public class MicroView extends RelativeLayout implements View.OnLayoutChangeListener { +public class MicroView extends FrameLayout implements View.OnLayoutChangeListener { private static final String TAG = "MicroView"; public RecyclerView recyclerView; private SparseArray faceImageViews; private SparseArray dragonBarImageViews; - - private int[] realPositions = {1, 5, 2, 6, 0, 3, 7, 4, 8}; - private Context mContext; private int giftWidth; private int giftHeight; private Disposable subscribe; - private KtvView ktvView; - private LayoutMicroViewBinding mBinding; - private boolean isNeedResetMicCenterPoint = true; private DatingItemDecoration datingItemDecoration; @@ -206,7 +190,7 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList int y = (location[1] + child.getHeight() / 2) - giftHeight / 2; // 放置表情占位image view ImageView face = array.get(micPosition); - LayoutParams params = new LayoutParams(giftHeight, giftHeight); + LayoutParams params = new LayoutParams(giftWidth, giftHeight); child.getLocationInWindow(location); int[] containerLocation = new int[2]; this.getLocationInWindow(containerLocation); @@ -232,7 +216,6 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList private void init(final Context context) { this.mContext = context; inflate(mContext, R.layout.layout_micro_view, this); - mBinding = DataBindingUtil.bind(findViewById(R.id.container)); recyclerView = findViewById(R.id.recycler_view); recyclerView.addOnLayoutChangeListener(this); if (AvRoomDataManager.get().isCpRoom()) { @@ -240,42 +223,16 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList } else { bindAdapter(new MicroViewAdapter(mContext)); } - ktvView = findViewById(R.id.view_ktv); - ViewGroup.LayoutParams ktvParam = ktvView.getLayoutParams(); - ktvParam.height = (UIUtil.getScreenWidth(context) - UIUtil.dip2px(context, 24)) * 198 / 352; - - giftWidth = UIUtil.dip2px(mContext, 80); - giftHeight = UIUtil.dip2px(mContext, 80); + giftWidth = UIUtil.dip2px(mContext, 16); + giftHeight = UIUtil.dip2px(mContext, 16); faceImageViews = new SparseArray<>(10); dragonBarImageViews = new SparseArray<>(9); - mBinding.setRoomInfo(AvRoomDataManager.get().mCurrentRoomInfo); - } public void updateRoomInfo() { - RoomInfo roomInfo = AvRoomDataManager.get().mCurrentRoomInfo; - if (roomInfo == null) return; - mBinding.setRoomInfo(roomInfo); - mBinding.setKtvModel(roomInfo.isOpenKTV); - - if (!TextUtils.isEmpty(roomInfo.getRoomDesc())) { - mBinding.tvRoomDesc.setText(RegexUtil.getPrintableString(roomInfo.getRoomDesc())); - } else { - if (AvRoomDataManager.get().isManager()) { - mBinding.tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_manager_edit_desc)); - } else { - mBinding.tvRoomDesc.setText(BasicConfig.INSTANCE.getAppContext().getString(R.string.room_no_desc)); - } - } - if (AvRoomDataManager.get().isManager()) { - mBinding.ivRoomCanEdit.setVisibility(VISIBLE); - } else { - mBinding.ivRoomCanEdit.setVisibility(GONE); - } - mBinding.tvRoomType.setText(roomInfo.getRoomTag()); } @SuppressLint("CheckResult") @@ -388,31 +345,16 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList } } - private boolean isKtvMode; public void openKtvMode() { - isKtvMode = true; - mBinding.setKtvModel(isKtvMode); - ktvView.setVisibility(VISIBLE); - //修复成员刚进房间,变ktv模式后,关闭按钮没出现的问题 - ktvView.updateCloseBtnNoSong(); - if (!AvRoomDataManager.get().isCpRoom()) { - bindAdapter(new KtvMicroViewAdapter(mContext)); - } else { - resetPoint(); - } - if (!AudioEngineManager.get().isOpenKtv()) { - AudioEngineManager.get().openKtvModel(); - } + } - public void resetPoint() { - /* recyclerView.postDelayed(() -> { - faceImageViews = setMicCenterPoint(faceImageViews); - dragonBarImageViews = setMicCenterPoint(dragonBarImageViews); - }, 500);*/ + public void closeKtvMode() { + } + public void bindAdapter(BaseMicroViewAdapter adapter) { if (adapter instanceof DatingMicroViewAdapter) { if (datingItemDecoration == null) datingItemDecoration = new DatingItemDecoration(); @@ -422,19 +364,6 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList } adapter.bindToRecyclerView(recyclerView); adapter.setOnMicroItemClickListener(onMicroItemClickListener); - resetPoint(); - } - - public void closeKtvMode() { - isKtvMode = false; - mBinding.setKtvModel(false); - ktvView.setVisibility(GONE); - if (AvRoomDataManager.get().isCpRoom()) { - bindAdapter(new CpMicroViewAdapter(mContext)); - } else { - bindAdapter(new MicroViewAdapter(mContext)); - } - AudioEngineManager.get().closeKtvModel(); } public void switchToDatingMode() { @@ -452,25 +381,4 @@ public class MicroView extends RelativeLayout implements View.OnLayoutChangeList imageView.clearAnimation(); } - private int getRealPosition(int position) { - return isKtvMode && !AvRoomDataManager.get().isCpRoom() ? realPositions[position] : position; - } - - /** - * 根据坑位查找recyclerView的子View - * 如果是ktv模式的话,要额外处理 - * - * @param position 就是坑位(-1到7)的值+1 - * @return 坑位对应的recyclerView的子View - */ - private int getWavePosition(int position) { - if (isKtvMode && !AvRoomDataManager.get().isCpRoom()) { - for (int i = 0; i < realPositions.length; i++) { - if (position == realPositions[i]) { - return i; - } - } - } - return position; - } } diff --git a/app/src/main/res/drawable-xhdpi/ic_room_mic_right.png b/app/src/main/res/drawable-xhdpi/ic_room_mic_right.png new file mode 100644 index 000000000..8503cd391 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_room_mic_right.png differ diff --git a/app/src/main/res/drawable/bg_mini_mic_entrance.xml b/app/src/main/res/drawable/bg_mini_mic_entrance.xml new file mode 100644 index 000000000..3dceb5567 --- /dev/null +++ b/app/src/main/res/drawable/bg_mini_mic_entrance.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_chatroom_game_main.xml b/app/src/main/res/layout/fragment_chatroom_game_main.xml index e7826c584..1ddbb7bca 100644 --- a/app/src/main/res/layout/fragment_chatroom_game_main.xml +++ b/app/src/main/res/layout/fragment_chatroom_game_main.xml @@ -22,6 +22,11 @@ android:orientation="vertical" tools:background="#000"> + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_micro_game_mini.xml b/app/src/main/res/layout/item_micro_game_mini.xml new file mode 100644 index 000000000..e6189e396 --- /dev/null +++ b/app/src/main/res/layout/item_micro_game_mini.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_micro_view.xml b/app/src/main/res/layout/layout_micro_view.xml index 0f1f1c46a..ffc0e17bb 100644 --- a/app/src/main/res/layout/layout_micro_view.xml +++ b/app/src/main/res/layout/layout_micro_view.xml @@ -1,137 +1,8 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 000000000..50048396c --- /dev/null +++ b/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,9 @@ + + + + + + + fengkongcloud.com + + \ No newline at end of file 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 755841e32..1ab1049e7 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 @@ -30,6 +30,7 @@ android:id="@+id/ll_ktv_top" android:layout_width="match_parent" android:layout_height="32dp" + android:layout_marginTop="100dp" android:orientation="horizontal" android:visibility="@{(ktvModel || roomInfo.type==5) ? View.VISIBLE : View.GONE}"> diff --git a/app/src/module_mini_world/res/layout/fragment_game_room.xml b/app/src/module_mini_world/res/layout/fragment_game_room.xml new file mode 100644 index 000000000..2ae9250b5 --- /dev/null +++ b/app/src/module_mini_world/res/layout/fragment_game_room.xml @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/build.gradle b/core/build.gradle index 1f316f3cb..c6a65e078 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 29 defaultConfig { - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" diff --git a/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/home/model/HomeModel.kt b/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/home/model/HomeModel.kt index eddcef20c..63eb02f09 100644 --- a/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/home/model/HomeModel.kt +++ b/core/src/diff_src_erban/java/com/yizhuan/xchat_android_core/home/model/HomeModel.kt @@ -11,9 +11,7 @@ import com.yizhuan.xchat_android_core.utils.net.RxHelper import com.yizhuan.xchat_android_core.utils.net.launchRequest import com.yizhuan.xchat_android_library.net.rxnet.RxNet import io.reactivex.Single -import retrofit2.http.GET -import retrofit2.http.POST -import retrofit2.http.Query +import retrofit2.http.* object HomeModel : BaseModel() { @@ -85,6 +83,23 @@ object HomeModel : BaseModel() { }.compose(RxHelper.handleSchAndExce()) } + + fun getGameCode(): Single { + return api.getCode("https://fat-mgp-hello.sudden.ltd/login", AuthModel.get().currentUid) + .flatMap { unReadCountInfoServiceResult -> + if (unReadCountInfoServiceResult.isSuccess) { + val unReadCountInfo = unReadCountInfoServiceResult.data + if (unReadCountInfo != null) { + Single.just(unReadCountInfoServiceResult.data?.total ?: 0) + } else { + Single.just(0) + } + } else { + Single.just(0) + } + }.compose(RxHelper.handleSchAndExce()) + } + suspend fun getHomeBanner(type: String): List? = launchRequest { api.apiHomeBanner( @@ -171,6 +186,18 @@ object HomeModel : BaseModel() { @POST("interactive/unreadCount") fun getUnreadCount(@Query("uid") uid: Long): Single> + /** + * 获取互动消息未读数量 + * + * @param uid + * @return + */ + @POST + fun getCode( + @Url url: String, + @Query("user_id") uid: Long + ): Single> + /** * 首页Banner * diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameCodeInfo.kt b/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameCodeInfo.kt new file mode 100644 index 000000000..8a155d344 --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameCodeInfo.kt @@ -0,0 +1,6 @@ +package com.yizhuan.xchat_android_core.room.game + +data class GameCodeInfo( + val code: String, + val expireDate: Long +) \ No newline at end of file diff --git a/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameModel.kt b/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameModel.kt new file mode 100644 index 000000000..ef8212fba --- /dev/null +++ b/core/src/main/java/com/yizhuan/xchat_android_core/room/game/GameModel.kt @@ -0,0 +1,69 @@ +package com.yizhuan.xchat_android_core.room.game + +import com.yizhuan.xchat_android_core.auth.AuthModel +import com.yizhuan.xchat_android_core.base.BaseModel +import com.yizhuan.xchat_android_core.bean.response.ServiceResult +import com.yizhuan.xchat_android_core.community.CommunityConstant +import com.yizhuan.xchat_android_core.community.bean.UnReadCountInfo +import com.yizhuan.xchat_android_core.home.bean.BannerInfo +import com.yizhuan.xchat_android_core.utils.net.RxHelper +import com.yizhuan.xchat_android_core.utils.net.launchRequest +import com.yizhuan.xchat_android_library.net.rxnet.RxNet +import io.reactivex.Single +import retrofit2.http.* + +object GameModel : BaseModel() { + + private val api = RxNet.create(Api::class.java) + + fun getGameCode(): Single { + return api.getGameCode(AuthModel.get().currentUid) + //.compose(RxHelper.handleBeanData()) + .compose(RxHelper.handleSchAndExce()) + } + + suspend fun getHomeBanner(type: String): List? = + launchRequest { + api.apiHomeBanner( + type, AuthModel.get().currentUid.toString(), + CommunityConstant.VERSION_VALID_TYPE, + AuthModel.get().ticket + ) + } + + + + private interface Api { + + /** + * + * + * @param uid + * @return + */ + @FormUrlEncoded + @POST("/miniGame/getCode") + fun getGameCode( + @Field("uid") uid: Long + ): Single + + /** + * 首页Banner + * + * @param type + * @param uid + * @param types + * @param ticket + * @return + */ + @GET("/home/banner") + suspend fun apiHomeBanner( + @Query("type") type: String, + @Query("uid") uid: String, + @Query("types") types: String, + @Query("ticket") ticket: String + ): ServiceResult> + + } + +} \ No newline at end of file diff --git a/library/build.gradle b/library/build.gradle index ffbeae3d2..a3e2ef91d 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -4,7 +4,7 @@ apply plugin: 'kotlin-android' android { compileSdkVersion 29 defaultConfig { - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" diff --git a/nim_uikit/build.gradle b/nim_uikit/build.gradle index ee3cede00..f0a691145 100644 --- a/nim_uikit/build.gradle +++ b/nim_uikit/build.gradle @@ -7,7 +7,7 @@ android { buildToolsVersion '28.0.3' defaultConfig { - minSdkVersion 19 + minSdkVersion 21 targetSdkVersion 29 renderscriptTargetApi 26