|
|
@@ -0,0 +1,353 @@
|
|
|
+package com.adealink.weparty.room.sdk.controller.impl
|
|
|
+
|
|
|
+import android.os.Handler
|
|
|
+import com.adealink.frame.base.Rlt
|
|
|
+import com.adealink.frame.log.Log
|
|
|
+import com.adealink.frame.network.ISocketNotify
|
|
|
+import com.adealink.frame.network.data.Res
|
|
|
+import com.adealink.frame.room.data.FlowStateInfo
|
|
|
+import com.adealink.frame.room.data.JoinChannelReason
|
|
|
+import com.adealink.frame.room.data.LeaveChannelReason
|
|
|
+import com.adealink.frame.room.data.LeaveRoomReason
|
|
|
+import com.adealink.frame.room.data.RoomMemberOnlineInfo
|
|
|
+import com.adealink.frame.room.data.TAG_ROOM_MEMBER
|
|
|
+import com.adealink.weparty.App
|
|
|
+import com.adealink.weparty.module.profile.ProfileModule
|
|
|
+import com.adealink.weparty.module.profile.data.UserInfo
|
|
|
+import com.adealink.weparty.module.room.data.MemberRoomRole
|
|
|
+import com.adealink.weparty.module.room.data.RoomUserInfo
|
|
|
+import com.adealink.weparty.room.constant.getRoomErrorByError
|
|
|
+import com.adealink.weparty.room.data.AddRoomAdminReq
|
|
|
+import com.adealink.weparty.room.data.DelRoomAdminReq
|
|
|
+import com.adealink.weparty.room.data.KickOutRoomNotify
|
|
|
+import com.adealink.weparty.room.data.KickOutRoomReq
|
|
|
+import com.adealink.weparty.room.data.KickOutRoomRes
|
|
|
+import com.adealink.weparty.room.data.RoomMemberOnlineInfoNotify
|
|
|
+import com.adealink.weparty.room.datasource.remote.RoomHttpService
|
|
|
+import com.adealink.weparty.room.sdk.context.IRoomContext
|
|
|
+import com.adealink.weparty.room.sdk.controller.BaseController
|
|
|
+import com.adealink.weparty.room.sdk.controller.IWPMemberController
|
|
|
+import com.adealink.weparty.room.sdk.listener.IWPMemberListener
|
|
|
+import com.adealink.weparty.room.stat.RoomDurationReporter
|
|
|
+import kotlinx.coroutines.launch
|
|
|
+
|
|
|
+/**
|
|
|
+ * Created by sunxiaodong on 2021/5/3.
|
|
|
+ */
|
|
|
+class WPMemberController(override val ctx: IRoomContext, serialHandler: Handler) :
|
|
|
+ BaseController<IWPMemberListener>(ctx, serialHandler), IWPMemberController<IWPMemberListener> {
|
|
|
+
|
|
|
+ private val roomHttpService by lazy { App.instance.networkService.getHttpService(RoomHttpService::class.java) }
|
|
|
+ private var onlineInfoVersion = 0L
|
|
|
+ private var onlineMemberCount = 0L //在线成员数
|
|
|
+
|
|
|
+ private val kickOutRoomNotify = object : ISocketNotify<KickOutRoomNotify> {
|
|
|
+
|
|
|
+ override val uri: String = "USER_KICK_NOTIFY"
|
|
|
+
|
|
|
+ override fun needHandle(data: KickOutRoomNotify?): Boolean {
|
|
|
+ return data != null && ctx.roomService.joinController.getJoinedRoomId() == data.roomId
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onNotify(data: KickOutRoomNotify) {
|
|
|
+ launch {
|
|
|
+ ctx.roomService.joinController.tryLeaveRoom(LeaveRoomReason.KICK_OUT, false)
|
|
|
+ listeners.dispatch {
|
|
|
+ it.onKickOutRoom(data.kickReason)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private val roomMemberOnlineInfoNotify = object : ISocketNotify<RoomMemberOnlineInfoNotify> {
|
|
|
+
|
|
|
+ override val uri: String = "ROOM_ONLINE_NOTIFY"
|
|
|
+
|
|
|
+ override fun needHandle(data: RoomMemberOnlineInfoNotify?): Boolean {
|
|
|
+ return data != null && ctx.roomService.joinController.getJoinedRoomId() == data.roomId
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onNotify(data: RoomMemberOnlineInfoNotify) {
|
|
|
+ handleMemberOnlineInfo(data.memberOnlineInfo, data.ownerInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun isJoinedRoomOwner(uid: Long): Boolean {
|
|
|
+ return ctx.roomService.joinController.joinedRoomInfo?.ownerUid == uid
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun getJoinedRoomOwnerUid(): Long? {
|
|
|
+ return ctx.roomService.joinController.joinedRoomInfo?.ownerUid
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun isJoinedRoomAdmin(uid: Long): Boolean {
|
|
|
+ return ctx.roomService.joinController.joinedRoomInfo?.adminList?.contains(uid) == true
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun getJoinedRoomMemberRole(uid: Long): MemberRoomRole {
|
|
|
+ return when {
|
|
|
+ isJoinedRoomOwner(uid) -> MemberRoomRole.OWNER
|
|
|
+ isJoinedRoomAdmin(uid) -> MemberRoomRole.ADMIN
|
|
|
+ ctx.roomService.joinController.isRoomJoined() -> MemberRoomRole.AUDIENCE
|
|
|
+ else -> MemberRoomRole.UNKNOWN
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun isJoinedRoomOwnerOrAdmin(uid: Long): Boolean {
|
|
|
+ return getJoinedRoomMemberRole(uid).isRoomOwnerOrAdmin()
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun handleMemberOnlineInfo(
|
|
|
+ memberOnlineInfo: RoomMemberOnlineInfo,
|
|
|
+ ownerInfo: RoomUserInfo? = null,
|
|
|
+ token: String? = null
|
|
|
+ ) {
|
|
|
+
|
|
|
+ launch {
|
|
|
+ if (memberOnlineInfo.version <= onlineInfoVersion) {
|
|
|
+ Log.d(
|
|
|
+ TAG_ROOM_MEMBER,
|
|
|
+ "version return, onlineInfoVersion:$onlineInfoVersion,memberOnlineInfo.version:${memberOnlineInfo.version},"
|
|
|
+ )
|
|
|
+ return@launch
|
|
|
+ }
|
|
|
+ ownerInfo?.userInfo?.let { memberInfo ->
|
|
|
+ updateCacheMemberInfo(memberInfo)
|
|
|
+ ownerInfo.configInfo?.let {
|
|
|
+ ProfileModule.handleUserConfigUpdate(memberInfo.uid, it)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ onlineInfoVersion = memberOnlineInfo.version
|
|
|
+ onlineMemberCount = memberOnlineInfo.onlineMemberCount
|
|
|
+ Log.d(
|
|
|
+ TAG_ROOM_MEMBER,
|
|
|
+ "version return, onlineMemberCount:$onlineMemberCount,isMediaUsing:${ctx.mediaService.isMediaUsing()},"
|
|
|
+ )
|
|
|
+ //根据房间成员数执行媒体进出,节约成本
|
|
|
+ if (onlineMemberCount > 1) {
|
|
|
+ ctx.roomService.joinController.joinChannel(
|
|
|
+ JoinChannelReason.ON_LINE_MEMBER_GT_1,
|
|
|
+ token
|
|
|
+ )
|
|
|
+ } else if (!ctx.mediaService.isMediaUsing() && ctx.mediaService.isChannelJoined()) {
|
|
|
+ ctx.roomService.joinController.leaveChannel(LeaveChannelReason.ON_LINE_MEMBER_LE_1)
|
|
|
+ }
|
|
|
+ notifyMemberCountChanged(onlineMemberCount)
|
|
|
+ if (isJoinedRoomOwner(ctx.appSupplier.selfUid)) {
|
|
|
+ RoomDurationReporter.memberChange(onlineMemberCount)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun getOnlineMemberCount(): Long {
|
|
|
+ return onlineMemberCount
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun notifyMemberCountChanged(count: Long) {
|
|
|
+ listeners.dispatch {
|
|
|
+ it.onMemberCountChanged(count)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onRoomIn(flowStateInfo: FlowStateInfo) {
|
|
|
+ App.instance.networkService.subscribeNotify(kickOutRoomNotify)
|
|
|
+ App.instance.networkService.subscribeNotify(roomMemberOnlineInfoNotify)
|
|
|
+ val onlineInfo = flowStateInfo.onlineInfo ?: return
|
|
|
+ handleMemberOnlineInfo(onlineInfo, null, flowStateInfo.token)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onRoomLeaved(flowStateInfo: FlowStateInfo) {
|
|
|
+ reset()
|
|
|
+ App.instance.networkService.unSubscribeNotify(kickOutRoomNotify)
|
|
|
+ App.instance.networkService.unSubscribeNotify(roomMemberOnlineInfoNotify)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun reset() {
|
|
|
+ onlineInfoVersion = 0
|
|
|
+ onlineMemberCount = 0
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun kickOutRoom(uid: Long): Rlt<Res<KickOutRoomRes>> {
|
|
|
+ val joinedRoomIdRlt = ctx.roomService.joinController.getJoinedRoomIdRlt()
|
|
|
+ if (joinedRoomIdRlt is Rlt.Failed) {
|
|
|
+ return joinedRoomIdRlt
|
|
|
+ }
|
|
|
+
|
|
|
+ val roomId = (joinedRoomIdRlt as Rlt.Success).data
|
|
|
+ return when (val rlt = roomHttpService.kickOutRoom(KickOutRoomReq(roomId, uid))
|
|
|
+ .apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "kickOutRoom, roomId:${roomId}, uid:${uid}", this)
|
|
|
+ }) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ rlt
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> {
|
|
|
+ Rlt.Failed(getRoomErrorByError(rlt.error))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onCreate() {
|
|
|
+ super.onCreate()
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onDestroy() {
|
|
|
+ super.onDestroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getMembers(): Rlt<MutableList<UserInfo>> {
|
|
|
+ val joinedRoomIdRlt = ctx.roomService.joinController.getJoinedRoomIdRlt()
|
|
|
+ if (joinedRoomIdRlt is Rlt.Failed) {
|
|
|
+ return joinedRoomIdRlt
|
|
|
+ }
|
|
|
+
|
|
|
+ val roomId = (joinedRoomIdRlt as Rlt.Success).data
|
|
|
+ return when (val result = roomHttpService.getRoomMembers(roomId)) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ val members = result.data.data?.members?.toSet() ?: emptySet()
|
|
|
+ val userInfos = (ProfileModule.getUsersInfoByUid(members) as? Rlt.Success)?.data
|
|
|
+ Rlt.Success(
|
|
|
+ members.map {
|
|
|
+ userInfos?.get(it) ?: UserInfo.emptyUserInfo(it, "")
|
|
|
+ }.toMutableList()
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> result
|
|
|
+ }.apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "getMembers, roomId:${roomId}", this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getMembers(page: Int, size: Int): Rlt<MutableList<UserInfo>> {
|
|
|
+ val joinedRoomIdRlt = ctx.roomService.joinController.getJoinedRoomIdRlt()
|
|
|
+ if (joinedRoomIdRlt is Rlt.Failed) {
|
|
|
+ return joinedRoomIdRlt
|
|
|
+ }
|
|
|
+
|
|
|
+ val roomId = (joinedRoomIdRlt as Rlt.Success).data
|
|
|
+ return when (val result = roomHttpService.getRoomMembers(roomId)) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ val members = result.data.data?.members?.toSet() ?: emptySet()
|
|
|
+ val userInfos = (ProfileModule.getUsersInfoByUid(members) as? Rlt.Success)?.data
|
|
|
+ Rlt.Success(
|
|
|
+ members.map {
|
|
|
+ userInfos?.get(it) ?: UserInfo.emptyUserInfo(it, "")
|
|
|
+ }.toMutableList()
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> result
|
|
|
+ }.apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "getMembers, roomId:${roomId}", this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getMemberInfoWithRetry(uid: Long): Rlt<UserInfo> {
|
|
|
+ var retry = 0
|
|
|
+ var result: Rlt<UserInfo>
|
|
|
+ do {
|
|
|
+ result = getMemberInfo(uid)
|
|
|
+ retry++
|
|
|
+ } while (result is Rlt.Failed && retry < 3)
|
|
|
+ return result
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getMemberInfo(uid: Long): Rlt<UserInfo> {
|
|
|
+ val roomMember = ProfileModule.getCacheUserInfo(uid)
|
|
|
+ if (roomMember != null) {
|
|
|
+ return Rlt.Success(roomMember)
|
|
|
+ }
|
|
|
+
|
|
|
+ return when (val result = ProfileModule.getUserInfoByUid(uid)) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ Rlt.Success(result.data)
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> {
|
|
|
+ result
|
|
|
+ }
|
|
|
+ }.apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "getMemberInfo, uid:${uid}", this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getMembersInfo(uidSet: Set<Long>): Rlt<Map<Long, UserInfo>> {
|
|
|
+ val uidToMemberMap = hashMapOf<Long, UserInfo>()
|
|
|
+ val noCacheMemberUidSet = hashSetOf<Long>()
|
|
|
+ uidSet.forEach {
|
|
|
+ val roomMember = ProfileModule.getCacheUserInfo(it)
|
|
|
+ if (roomMember == null) {
|
|
|
+ noCacheMemberUidSet.add(it)
|
|
|
+ } else {
|
|
|
+ uidToMemberMap[it] = roomMember
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (noCacheMemberUidSet.isEmpty()) {
|
|
|
+ return Rlt.Success(uidToMemberMap)
|
|
|
+ }
|
|
|
+
|
|
|
+ return when (val result = ProfileModule.getUsersInfoByUid(noCacheMemberUidSet)) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ result.data.forEach {
|
|
|
+ uidToMemberMap[it.key] = it.value
|
|
|
+ }
|
|
|
+ return Rlt.Success(uidToMemberMap)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> result
|
|
|
+ }.apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "getMembersInfo, uidSet:${uidSet}", this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun addRoomAdmin(uid: Long): Rlt<Any> {
|
|
|
+ return roomHttpService.addRoomAdmin(AddRoomAdminReq(uid))
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun delRoomAdmin(uid: Long): Rlt<Any> {
|
|
|
+ return roomHttpService.delRoomAdmin(DelRoomAdminReq(adminId = uid))
|
|
|
+ }
|
|
|
+
|
|
|
+ override suspend fun getRankBoardMembers(): Rlt<MutableList<UserInfo>> {
|
|
|
+ val joinedRoomIdRlt = ctx.roomService.joinController.getJoinedRoomIdRlt()
|
|
|
+ if (joinedRoomIdRlt is Rlt.Failed) {
|
|
|
+ return joinedRoomIdRlt
|
|
|
+ }
|
|
|
+ val roomId = (joinedRoomIdRlt as Rlt.Success).data
|
|
|
+ return when (val result = roomHttpService.getRankBoardRoomMembers(roomId)) {
|
|
|
+ is Rlt.Success -> {
|
|
|
+ val roomMembersRes = result.data.data!!
|
|
|
+ val members = roomMembersRes.members
|
|
|
+ val memberInfos = mutableListOf<UserInfo>()
|
|
|
+ val userInfoMap =
|
|
|
+ (ProfileModule.getUsersInfoByUid(members.toSet()) as? Rlt.Success)?.data
|
|
|
+ members.onEach { uid ->
|
|
|
+ userInfoMap?.get(uid)?.let { roomMember ->
|
|
|
+ memberInfos.add(roomMember)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Rlt.Success(memberInfos)
|
|
|
+ }
|
|
|
+
|
|
|
+ is Rlt.Failed -> result
|
|
|
+ }.apply {
|
|
|
+ Log.logRltD(TAG_ROOM_MEMBER, "getRankBoardMembers, roomId:${roomId}", this)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun updateCacheMemberInfo(member: UserInfo) {
|
|
|
+ ProfileModule.updateCacheUserInfo(member)
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun notifySelfRoleChanged(before: MemberRoomRole, after: MemberRoomRole) {
|
|
|
+ listeners.dispatch {
|
|
|
+ it.onSelfRoleChanged(before, after)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|