Browse Source

feat: 完善房间在线成员组件

DoggyZhang 1 year ago
parent
commit
799a1ced4e
37 changed files with 1187 additions and 595 deletions
  1. 2 2
      app/src/main/java/com/adealink/weparty/commonui/drag/BaseDragView.kt
  2. BIN
      app/src/main/res/drawable-xhdpi/common_green_camera_ic.png
  3. BIN
      app/src/main/res/drawable-xhdpi/common_pen_ic.png
  4. BIN
      app/src/main/res/drawable-xhdpi/commonui_dialog_close_ic.png
  5. 6 0
      app/src/main/res/values/styles.xml
  6. 2 1
      frame/room/src/main/java/com/adealink/frame/room/data/Tags.kt
  7. 94 256
      module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomDetailInfoFragment.kt
  8. 331 0
      module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomOnlineUserFragment.kt
  9. 19 17
      module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomSettingFragment.kt
  10. 281 0
      module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomSummaryFragment.kt
  11. 0 1
      module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicFactory.kt
  12. 3 1
      module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicLayer.kt
  13. 0 5
      module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomPageFragment.kt
  14. 7 32
      module/room/src/main/java/com/adealink/weparty/room/create/RoomCreateActivity.kt
  15. 2 0
      module/room/src/main/java/com/adealink/weparty/room/interceptor/EnterRoomUriInterceptor.kt
  16. 16 17
      module/room/src/main/java/com/adealink/weparty/room/member/comp/RoomOnlineMemberComp.kt
  17. 2 1
      module/room/src/main/java/com/adealink/weparty/room/member/listener/IMemberMedalListener.kt
  18. 9 0
      module/room/src/main/java/com/adealink/weparty/room/member/listener/IOnlineMemberListener.kt
  19. 11 0
      module/room/src/main/java/com/adealink/weparty/room/member/manager/IOnlineMemberManager.kt
  20. 100 0
      module/room/src/main/java/com/adealink/weparty/room/member/manager/OnlineMemberManager.kt
  21. 47 0
      module/room/src/main/java/com/adealink/weparty/room/member/viewmodel/RoomOnlineMemberViewModel.kt
  22. 9 15
      module/room/src/main/java/com/adealink/weparty/room/member/widget/RoomOnlineMemberDragView.kt
  23. 17 7
      module/room/src/main/java/com/adealink/weparty/room/member/widget/RoomOnlineMemberView.kt
  24. 1 11
      module/room/src/main/java/com/adealink/weparty/room/playcenter/RoomPlayCenterPanelFragment.kt
  25. 1 1
      module/room/src/main/java/com/adealink/weparty/room/sdk/listener/IWPMemberListener.kt
  26. 3 0
      module/room/src/main/java/com/adealink/weparty/room/viewmodel/RoomViewModelFactory.kt
  27. BIN
      module/room/src/main/res/drawable-xhdpi/room_create_camera_ic.png
  28. BIN
      module/room/src/main/res/drawable-xhdpi/room_create_input_room_name_ic.png
  29. BIN
      module/room/src/main/res/drawable-xhdpi/room_room_create_bg.png
  30. 6 0
      module/room/src/main/res/drawable/room_create_input_bg.xml
  31. 54 68
      module/room/src/main/res/layout/activity_room_create.xml
  32. 23 114
      module/room/src/main/res/layout/fragment_room_detail_info.xml
  33. 55 5
      module/room/src/main/res/layout/fragment_room_online_user.xml
  34. 78 31
      module/room/src/main/res/layout/fragment_room_summary.xml
  35. 1 3
      module/room/src/main/res/layout/layout_room_online_member.xml
  36. 6 7
      module/room/src/main/res/layout/layout_room_online_member_view.xml
  37. 1 0
      module/room/src/main/res/values/strings.xml

+ 2 - 2
app/src/main/java/com/adealink/weparty/commonui/drag/BaseDragView.kt

@@ -27,7 +27,7 @@ open class BaseDragView(context: Context, attrs: AttributeSet? = null, defStyleA
     private var mAvailableArea = Rect()
 
     private var lastLocationKey: String? = null
-    private var resetToLastLocationAfterLayout = true
+    open var resetToLastLocationAfterLayout = false
     private var lastDragX: Int = -1
     private var lastDragY: Int = -1
 
@@ -69,7 +69,7 @@ open class BaseDragView(context: Context, attrs: AttributeSet? = null, defStyleA
             return
         }
         val ta = context.obtainStyledAttributes(attrs, R.styleable.BaseFloatView)
-        resetToLastLocationAfterLayout = ta.getBoolean(R.styleable.BaseFloatView_reset_to_last_location, true)
+        resetToLastLocationAfterLayout = ta.getBoolean(R.styleable.BaseFloatView_reset_to_last_location, resetToLastLocationAfterLayout)
         lastLocationKey = ta.getString(R.styleable.BaseFloatView_last_location_sp_key)
         ta.recycle()
     }

BIN
app/src/main/res/drawable-xhdpi/common_green_camera_ic.png


BIN
app/src/main/res/drawable-xhdpi/common_pen_ic.png


BIN
app/src/main/res/drawable-xhdpi/commonui_dialog_close_ic.png


+ 6 - 0
app/src/main/res/values/styles.xml

@@ -116,4 +116,10 @@
         <item name="liked_image">@drawable/cocosgame_orange_liked_ic</item>
     </style>
 
+    <style name="CommonEditText">
+        <item name="android:textColor">@color/color_222222</item>
+        <item name="android:textColorHint">@color/color_CCCCCC</item>
+        <item name="android:includeFontPadding">false</item>
+    </style>
+
 </resources>

+ 2 - 1
frame/room/src/main/java/com/adealink/frame/room/data/Tags.kt

@@ -18,4 +18,5 @@ const val TAG_ROOM_ROCKET = "${TAG_ROOM}_rocket"
 const val TAG_ROOM_PERMISSION = "${TAG_ROOM}_permission"
 const val TAG_ROOM_GLOBAL_BROADCAST = "${TAG_ROOM}_GlobalBroadcast"
 const val TAG_ROOM_GIFT = "${TAG_ROOM}_gift"
-const val TAG_ROOM_GAME = "${TAG_ROOM}_game"
+const val TAG_ROOM_GAME = "${TAG_ROOM}_game"
+const val TAG_ROOM_ONLINE_MEMBER = "${TAG_ROOM}_online_member"

+ 94 - 256
module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomDetailInfoFragment.kt

@@ -1,331 +1,169 @@
 package com.adealink.weparty.room.attr.info
 
-import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.KeyEvent
-import android.view.View
+import androidx.fragment.app.Fragment
 import androidx.fragment.app.viewModels
-import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
 import com.adealink.frame.aab.util.getCompatString
-import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
-import com.adealink.frame.ext.isUIValid
 import com.adealink.frame.mvvm.view.viewBinding
-import com.adealink.frame.util.noOpDelegate
+import com.adealink.frame.util.DisplayUtil
 import com.adealink.weparty.App
-import com.adealink.weparty.commonui.dialogfragment.showDialogFragment
 import com.adealink.weparty.commonui.ext.gone
-import com.adealink.weparty.commonui.ext.hide
 import com.adealink.weparty.commonui.ext.show
-import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
-import com.adealink.weparty.commonui.toast.util.showFailedToast
-import com.adealink.weparty.commonui.toast.util.showToast
+import com.adealink.weparty.commonui.recycleview.adapter.BaseTabFragmentStateAdapter
 import com.adealink.weparty.commonui.widget.BottomDialogFragment
-import com.adealink.weparty.commonui.widget.CommonDialog
-import com.adealink.weparty.module.follow.FollowModule
-import com.adealink.weparty.module.follow.data.FollowOpFrom
-import com.adealink.weparty.module.medal.MedalModule
-import com.adealink.weparty.module.medal.view.MedalItem
-import com.adealink.weparty.module.profile.ProfileModule
-import com.adealink.weparty.module.profile.data.UserInfo
-import com.adealink.weparty.module.rank.RankModule
-import com.adealink.weparty.module.rank.data.MarkItem
-import com.adealink.weparty.module.room.Room
 import com.adealink.weparty.module.room.data.MemberRoomRole
-import com.adealink.weparty.module.room.data.RoomData
-import com.adealink.weparty.module.room.sdk.data.RoomType
 import com.adealink.weparty.module.userprotect.UserProtectModule
 import com.adealink.weparty.module.userprotect.data.ReportFrom
-import com.adealink.weparty.module.userprotect.data.ReportType
 import com.adealink.weparty.room.R
-import com.adealink.weparty.room.attr.adapter.RoomMemberSearchEmptyViewBinder
-import com.adealink.weparty.room.attr.data.RoomMemberSearchEmptyData
-import com.adealink.weparty.room.attr.info.adapter.MemberDetailInfoViewBinder
-import com.adealink.weparty.room.attr.info.stat.RoomInfoStatEvent
-import com.adealink.weparty.room.attr.info.stat.RoomInfoStatEvent.Companion.reportBtnClick
-import com.adealink.weparty.room.constant.RoomCantKickAntiKickError
+import com.adealink.weparty.room.attr.info.viewmodel.RoomDetailInfoViewModel
 import com.adealink.weparty.room.databinding.FragmentRoomDetailInfoBinding
-import com.adealink.weparty.room.diff.RoomDataDiffUtil
-import com.adealink.weparty.room.member.RoomMemberInfoFragment
-import com.adealink.weparty.room.member.listener.IMemberMedalListener
-import com.adealink.weparty.room.member.listener.IMemberOperaListener
 import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
-import com.adealink.weparty.room.sdk.service.roomService
 import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
-import com.qmuiteam.qmui.widget.util.QMUIKeyboardHelper
-import com.adealink.weparty.R as APP_R
 
-/**
- * Created by sunxiaodong on 2021/6/24.
- */
-class RoomDetailInfoFragment : BottomDialogFragment(R.layout.fragment_room_detail_info),
-    IMemberOperaListener, IMemberMedalListener {
+class RoomDetailInfoFragment : BottomDialogFragment(R.layout.fragment_room_detail_info) {
 
     companion object {
         const val TAG = "RoomDetailInfoFragment"
+
+        private const val ROOM_SETTING_PAGE = 0L
+        private const val ROOM_ONLINE_USER_PAGE = 1L
+        private const val ROOM_SUMMARY_PAGE = 2L
+
+        private val OWNER_ADMIN_PAGES = listOf(ROOM_SETTING_PAGE, ROOM_ONLINE_USER_PAGE)
+        private val AUDIENCE_PAGES = listOf(ROOM_SUMMARY_PAGE)
+
+        private val UNKNOW_PAGE = -1
+        private val OWNER_ADMIN_PAGE = 0
+        private val AUDIENCE_PAGE = 1
     }
 
     override val fgTag: String = TAG
 
     private val binding by viewBinding(FragmentRoomDetailInfoBinding::bind)
-    private val adapter by fastLazy { MultiTypeListAdapter(RoomDataDiffUtil()) }
+    private val adapter by fastLazy { RoomDetailAdapter() }
     private val memberViewModel by viewModels<RoomMemberViewModel> { RoomViewModelFactory() }
-    private val followViewModel by fastLazy { FollowModule.getFollowViewModel(this.requireActivity()) }
-    private val medalViewModel by fastLazy { MedalModule.getMedalViewModel(requireActivity()) }
-    private val rankViewModel by fastLazy { RankModule.getRankViewModel(this) }
-    private val followedMap = HashMap<Long, Boolean>()
-    private var members = mutableListOf<UserInfo>()
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        RoomInfoStatEvent.reportShow()
-    }
+    private val dialogViewModel by viewModels<RoomDetailInfoViewModel>()
+    private var pageType = UNKNOW_PAGE
+    private var pages = listOf<Long>()
 
     override fun initViews() {
         super.initViews()
-        binding.memberList.layoutManager =
-            LinearLayoutManager(context, RecyclerView.VERTICAL, false)
-        adapter.register(MemberDetailInfoViewBinder(this, this))
-        adapter.register(RoomMemberSearchEmptyViewBinder())
-        binding.memberList.adapter = adapter
-        val ownerUid = memberViewModel.getJoinedRoomOwnerUid()
-        binding.reportIv.visibility =
-            if (ownerUid == ProfileModule.getMyUid()) View.GONE else View.VISIBLE
+        binding.vpContent.adapter = adapter
+        binding.tabTitle.createMediatorAndAttach(
+            binding.vpContent,
+            adapter,
+            0
+        )
         binding.reportIv.setOnClickListener {
-            val roomId =
-                App.instance.mediaManager.getJoinedMediaRoomId() ?: return@setOnClickListener
+            val roomId = App.instance.mediaManager.getJoinedMediaRoomId() ?: return@setOnClickListener
             UserProtectModule.showReportRoomDialog(roomId, ReportFrom.ROOM_DETAIL)
         }
-        binding.searchEditText.setOnKeyListener(object : View.OnKeyListener {
-
-            override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean {
-                if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) {
-                    QMUIKeyboardHelper.hideKeyboard(v)
-                    search()
-                    return true
-                }
-                return false
-            }
-
-        })
-        binding.searchEditText.addTextChangedListener(object : TextWatcher by noOpDelegate() {
-
-            override fun afterTextChanged(s: Editable) {
-                if (s.toString().trim().isEmpty()) {
-                    finishSearch()
-                }
-            }
-
-        })
-        binding.searchCancel.setOnClickListener {
-            binding.searchEditText.setText("")
-        }
-    }
-
-    override fun observeViewModel() {
-        super.observeViewModel()
-        memberViewModel.rankBoardRoomMembersLD.observe(viewLifecycleOwner) { rlt ->
-            when (rlt) {
-                is Rlt.Success -> {
-                    val members = rlt.data
-                    this.members.clear()
-                    this.members.addAll(members)
-                    notifyMembersChanged()
-                }
 
-                else -> {}
-            }
-        }
-        if (roomService.attrController.getRoomType() != RoomType.MIC_GRAB) {
-            binding.layoutRoomInfo.root.show()
-            binding.reportIv.show()
+        if (isOwnerAdminPage()) {
+            roleToAdmin()
         } else {
-            binding.layoutRoomInfo.root.gone()
-            binding.reportIv.hide()
+            roleToAudience()
         }
     }
 
-    private fun notifyMembersChanged() {
-        updateMemberCount(members.size)
-        adapter.submitList(members)
-    }
-
-    override fun initComponents() {
-        super.initComponents()
-        RoomInfoComp(this, binding.layoutRoomInfo, binding.familyInfoView).attach()
-    }
-
-    override fun loadData() {
-        super.loadData()
-        memberViewModel.getRankBoardRoomMembers()
+    private fun isOwnerAdminPage(): Boolean {
+        return memberViewModel.isIAmRoomOwner() || memberViewModel.isIAmRoomAdmin()
     }
 
-    override fun getMedalList(
-        userInfo: UserInfo,
-        callback: (List<MedalItem>?) -> Unit
-    ) {
-        if (!isUIValid()) {
-            callback.invoke(null)
-            return
-        }
-        medalViewModel?.getUserProfileMedalList(userInfo)?.observe(viewLifecycleOwner) {
-            callback.invoke(it)
-        } ?: let {
-            callback.invoke(null)
+    override fun observeViewModel() {
+        super.observeViewModel()
+        dialogViewModel.dismissLiveData.observe(viewLifecycleOwner) {
+            dismiss()
         }
-    }
-
-    override fun getUserProfileMarkList(
-        uid: Long,
-        goodsList: List<Long>?,
-        callback: (List<MarkItem>?) -> Unit
-    ) {
-        if (goodsList != null) {
-            rankViewModel?.getUserProfileMarkList(uid, goodsList)
-                ?.observe(viewLifecycleOwner) { list ->
-                    callback.invoke(list)
+        memberViewModel.roleChangeLD.observe(viewLifecycleOwner) {
+            when (it.second) {
+                MemberRoomRole.ADMIN -> {
+                    roleToAdmin()
                 }
-        }
-    }
 
-    override fun onMemberClick(member: UserInfo) {
-        showDialogFragment<RoomMemberInfoFragment>(parentFragmentManager, Bundle().apply {
-            putLong(Room.Common.EXTRA_UID, member.uid)
-        })
-        dismiss()
-    }
-
-    override fun onKickOutClick(member: UserInfo) {
-        showLoading()
-        memberViewModel.kickOutRoom(member.uid).observe(viewLifecycleOwner) { rlt ->
-            dismissLoading()
-            when (rlt) {
-                is Rlt.Success -> {
-                    this.members.find { it.uid == member.uid }?.let { member ->
-                        this.members.remove(member)
+                MemberRoomRole.AUDIENCE -> {
+                    if (it.first == MemberRoomRole.ADMIN) {
+                        roleToAudience()
                     }
-                    notifyMembersChanged()
                 }
 
-                is Rlt.Failed -> {
-                    if (rlt.error is RoomCantKickAntiKickError) {
-                        CommonDialog.Builder()
-                            .message(rlt.error.msg)
-                            .setShowDefaultCancel(false)
-                            .build()
-                            .show(childFragmentManager)
-                    } else {
-                        showFailedToast(rlt)
-                    }
-                }
+                else -> {}
             }
         }
     }
 
-    override fun onFollowClick(uid: Long) {
-        super.onFollowClick(uid)
-        val followed = followedMap[uid] ?: return
-        if (followed) {
-            unfollowUser(uid)
-            reportBtnClick(RoomInfoStatEvent.Btn.UN_FOLLOWING)
-        } else {
-            followUser(uid)
-            reportBtnClick(RoomInfoStatEvent.Btn.FOLLOWING)
+    private fun roleToAdmin() {
+        if (pageType == OWNER_ADMIN_PAGE) {
+            return
         }
+        binding.reportIv.gone()
+        pageType = OWNER_ADMIN_PAGE
+        pages = OWNER_ADMIN_PAGES
+        adapter.notifyDataSetChanged()
+        binding.vpContent.currentItem = 0
     }
 
-    override fun onReportClick(uid: Long) {
-        super.onReportClick(uid)
-        UserProtectModule.showReportUserDialog(uid, ReportFrom.ROOM_MEMBER, ReportType.USER_INFO)
-    }
-
-    override fun isFollowed(uid: Long): Boolean {
-        if (followedMap.containsKey(uid)) {
-            return followedMap[uid] ?: false
+    private fun roleToAudience() {
+        if (pages == AUDIENCE_PAGES) {
+            return
         }
-
-        followViewModel?.isUserFollowed(uid)
-        return false
+        binding.reportIv.show()
+        pageType = AUDIENCE_PAGE
+        pages = AUDIENCE_PAGES
+        adapter.notifyDataSetChanged()
+        binding.vpContent.currentItem = 0
     }
 
-    override fun isRoomOwner(uid: Long): Boolean {
-        return memberViewModel.isRoomOwner(uid)
-    }
+    //弹窗高度为屏幕高度的80%
+    override val height: Int
+        get() = (DisplayUtil.getScreenHeight() * 0.8f).toInt()
 
-    override fun isRoomAdmin(uid: Long): Boolean {
-        return memberViewModel.isRoomAdmin(uid)
-    }
+    internal inner class RoomDetailAdapter : BaseTabFragmentStateAdapter(this) {
 
-    override fun getMemberInfo(uid: Long, callback: (UserInfo?) -> Unit) {
-        memberViewModel.getRoomMemberInfo(uid).observe(viewLifecycleOwner) { memberRlt ->
-            when (memberRlt) {
-                is Rlt.Success -> {
-                    callback(memberRlt.data)
-                    //更新members
-                    val indexOfMember = members.indexOfFirst { it.uid == uid }
-                    members[indexOfMember] = memberRlt.data
+        override fun getTabName(pos: Int): String {
+            return when (pages.getOrNull(pos)) {
+                ROOM_SETTING_PAGE -> {
+                    getCompatString(R.string.room_setting)
                 }
 
-                is Rlt.Failed -> {
-                    callback(null)
+                ROOM_ONLINE_USER_PAGE -> {
+                    getCompatString(R.string.room_online_user)
+                }
+
+                else -> {
+                    //ROOM_SUMMARY_PAGE
+                    getCompatString(R.string.room_detail)
                 }
             }
         }
-    }
 
-    override fun getMemberRole(uid: Long): MemberRoomRole {
-        return memberViewModel.getRoomRole(uid)
-    }
-
-    private fun updateMemberCount(count: Int) {
-        binding.memberCount.text =
-            getCompatString(R.string.room_online_member_count, count)
-    }
-
-    private fun followUser(uid: Long) {
-        followViewModel?.followUser(
-            uid,
-            FollowOpFrom.ROOM_DETAIL,
-            followInRoom = App.instance.mediaManager.getJoinedMediaRoomId()
-        )?.observe(viewLifecycleOwner) {
-            showFailedToast(it)
+        override fun getItemCount(): Int {
+            return pages.size
         }
-    }
 
-    private fun unfollowUser(uid: Long) {
-        followViewModel?.unFollowUser(uid, FollowOpFrom.ROOM_DETAIL)?.observe(viewLifecycleOwner) {
-            showFailedToast(it)
+        override fun getItemId(position: Int): Long {
+            return pages.getOrNull(position) ?: RecyclerView.NO_ID
         }
-    }
 
-    private fun search() {
-        val keyword = binding.searchEditText.text.toString().trim()
-        if (keyword.isEmpty()) {
-            showToast(getCompatString(APP_R.string.common_input_empty))
-            return
+        override fun containsItem(itemId: Long): Boolean {
+            return pages.contains(itemId)
         }
 
-        binding.searchCancel.visibility = View.VISIBLE
-        val resultList = members.filter {
-            it.containsKeywordBySearch(keyword)
-        }
-        if (resultList.isEmpty()) {
-            showSearchEmpty()
-            return
-        }
-        adapter.submitList(resultList)
-    }
+        override fun createFragment(position: Int): Fragment {
+            return when (pages.getOrNull(position)) {
+                ROOM_SETTING_PAGE -> {
+                    RoomSettingFragment()
+                }
 
-    private fun finishSearch() {
-        binding.searchCancel.visibility = View.GONE
-        adapter.submitList(members)
-    }
+                ROOM_ONLINE_USER_PAGE -> {
+                    RoomOnlineUserFragment()
+                }
 
-    private fun showSearchEmpty() {
-        val resultList = mutableListOf<RoomData>()
-        resultList.add(RoomMemberSearchEmptyData)
-        adapter.submitList(resultList)
+                else -> {
+                    RoomSummaryFragment()
+                }
+            }
+        }
     }
 }

+ 331 - 0
module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomOnlineUserFragment.kt

@@ -0,0 +1,331 @@
+package com.adealink.weparty.room.attr.info
+
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.KeyEvent
+import android.view.View
+import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.ext.isUIValid
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.util.noOpDelegate
+import com.adealink.weparty.App
+import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.commonui.dialogfragment.showDialogFragment
+import com.adealink.weparty.commonui.ext.gone
+import com.adealink.weparty.commonui.ext.hide
+import com.adealink.weparty.commonui.ext.show
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.commonui.toast.util.showFailedToast
+import com.adealink.weparty.commonui.toast.util.showToast
+import com.adealink.weparty.commonui.widget.CommonDialog
+import com.adealink.weparty.module.follow.FollowModule
+import com.adealink.weparty.module.follow.data.FollowOpFrom
+import com.adealink.weparty.module.medal.MedalModule
+import com.adealink.weparty.module.medal.view.MedalItem
+import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.module.profile.data.UserInfo
+import com.adealink.weparty.module.rank.RankModule
+import com.adealink.weparty.module.rank.data.MarkItem
+import com.adealink.weparty.module.room.Room
+import com.adealink.weparty.module.room.data.MemberRoomRole
+import com.adealink.weparty.module.room.data.RoomData
+import com.adealink.weparty.module.room.sdk.data.RoomType
+import com.adealink.weparty.module.userprotect.UserProtectModule
+import com.adealink.weparty.module.userprotect.data.ReportFrom
+import com.adealink.weparty.module.userprotect.data.ReportType
+import com.adealink.weparty.room.R
+import com.adealink.weparty.room.attr.adapter.RoomMemberSearchEmptyViewBinder
+import com.adealink.weparty.room.attr.data.RoomMemberSearchEmptyData
+import com.adealink.weparty.room.attr.info.adapter.MemberDetailInfoViewBinder
+import com.adealink.weparty.room.attr.info.stat.RoomInfoStatEvent
+import com.adealink.weparty.room.attr.info.stat.RoomInfoStatEvent.Companion.reportBtnClick
+import com.adealink.weparty.room.constant.RoomCantKickAntiKickError
+import com.adealink.weparty.room.databinding.FragmentRoomOnlineUserBinding
+import com.adealink.weparty.room.diff.RoomDataDiffUtil
+import com.adealink.weparty.room.member.RoomMemberInfoFragment
+import com.adealink.weparty.room.member.listener.IMemberMedalListener
+import com.adealink.weparty.room.member.listener.IMemberOperaListener
+import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
+import com.adealink.weparty.room.sdk.service.roomService
+import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
+import com.qmuiteam.qmui.widget.util.QMUIKeyboardHelper
+import com.adealink.weparty.R as APP_R
+
+class RoomOnlineUserFragment : BaseFragment(R.layout.fragment_room_online_user),
+    IMemberOperaListener, IMemberMedalListener {
+
+    companion object {
+        const val TAG = "RoomOnlineUserFragment"
+    }
+
+    private val binding by viewBinding(FragmentRoomOnlineUserBinding::bind)
+    private val adapter by fastLazy { MultiTypeListAdapter(RoomDataDiffUtil()) }
+    private val memberViewModel by viewModels<RoomMemberViewModel> { RoomViewModelFactory() }
+    private val followViewModel by fastLazy { FollowModule.getFollowViewModel(this.requireActivity()) }
+    private val medalViewModel by fastLazy { MedalModule.getMedalViewModel(requireActivity()) }
+    private val rankViewModel by fastLazy { RankModule.getRankViewModel(this) }
+    private val followedMap = HashMap<Long, Boolean>()
+    private var members = mutableListOf<UserInfo>()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        RoomInfoStatEvent.reportShow()
+    }
+
+    override fun initViews() {
+        super.initViews()
+        binding.memberList.layoutManager =
+            LinearLayoutManager(context, RecyclerView.VERTICAL, false)
+        adapter.register(MemberDetailInfoViewBinder(this, this))
+        adapter.register(RoomMemberSearchEmptyViewBinder())
+        binding.memberList.adapter = adapter
+        val ownerUid = memberViewModel.getJoinedRoomOwnerUid()
+        binding.reportIv.visibility =
+            if (ownerUid == ProfileModule.getMyUid()) View.GONE else View.VISIBLE
+        binding.reportIv.setOnClickListener {
+            val roomId = App.instance.mediaManager.getJoinedMediaRoomId() ?: return@setOnClickListener
+            UserProtectModule.showReportRoomDialog(roomId, ReportFrom.ROOM_DETAIL)
+        }
+        binding.searchEditText.setOnKeyListener(object : View.OnKeyListener {
+
+            override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean {
+                if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) {
+                    QMUIKeyboardHelper.hideKeyboard(v)
+                    search()
+                    return true
+                }
+                return false
+            }
+
+        })
+        binding.searchEditText.addTextChangedListener(object : TextWatcher by noOpDelegate() {
+
+            override fun afterTextChanged(s: Editable) {
+                if (s.toString().trim().isEmpty()) {
+                    finishSearch()
+                }
+            }
+
+        })
+        binding.searchCancel.setOnClickListener {
+            binding.searchEditText.setText("")
+        }
+    }
+
+    override fun observeViewModel() {
+        super.observeViewModel()
+        memberViewModel.rankBoardRoomMembersLD.observe(viewLifecycleOwner) { rlt ->
+            when (rlt) {
+                is Rlt.Success -> {
+                    val members = rlt.data
+                    this.members.clear()
+                    this.members.addAll(members)
+                    notifyMembersChanged()
+                }
+                else -> {}
+            }
+        }
+        if (roomService.attrController.getRoomType() != RoomType.MIC_GRAB) {
+            binding.layoutRoomInfo.root.show()
+            binding.reportIv.show()
+        } else {
+            binding.layoutRoomInfo.root.gone()
+            binding.reportIv.hide()
+        }
+    }
+
+    private fun notifyMembersChanged() {
+        updateMemberCount(members.size)
+        adapter.submitList(members)
+    }
+
+    override fun initComponents() {
+        super.initComponents()
+        RoomInfoComp(this, binding.layoutRoomInfo, binding.familyInfoView).attach()
+    }
+
+    override fun loadData() {
+        super.loadData()
+        memberViewModel.getRankBoardRoomMembers()
+    }
+
+    override fun getMedalList(userInfo: UserInfo, callback: (List<MedalItem>?) -> Unit) {
+        if (!isUIValid()) {
+            callback.invoke(null)
+            return
+        }
+        medalViewModel?.getUserProfileMedalList(userInfo)?.observe(viewLifecycleOwner) {
+            callback.invoke(it)
+        } ?: let {
+            callback.invoke(null)
+        }
+    }
+
+//    override fun getMedalList(memberInfo: UserInfo, callback: (List<MedalItem>?) -> Unit) {
+//        if (!isUIValid()) {
+//            callback.invoke(null)
+//            return
+//        }
+//        medalViewModel?.getUserProfileMedalList(
+//            memberInfo.vipLevel,
+//            memberInfo.medals,
+//            memberInfo.medalLevels
+//        )?.observe(viewLifecycleOwner) {
+//            callback.invoke(it)
+//        } ?: let {
+//            callback.invoke(null)
+//        }
+//    }
+
+
+    override fun getUserProfileMarkList(uid: Long, goodsList: List<Long>?, callback: (List<MarkItem>?) -> Unit) {
+        if (goodsList != null) {
+            rankViewModel?.getUserProfileMarkList(uid, goodsList)?.observe(viewLifecycleOwner) { list ->
+                callback.invoke(list)
+            }
+        }
+    }
+
+    override fun onMemberClick(member: UserInfo) {
+        showDialogFragment<RoomMemberInfoFragment>(parentFragmentManager, Bundle().apply {
+            putLong(Room.Common.EXTRA_UID, member.uid)
+        })
+    }
+
+    override fun onKickOutClick(member: UserInfo) {
+        showLoading()
+        memberViewModel.kickOutRoom(member.uid).observe(viewLifecycleOwner) { rlt->
+            dismissLoading()
+            when (rlt) {
+                is Rlt.Success -> {
+                    this.members.find { it.uid == member.uid }?.let { member ->
+                        this.members.remove(member)
+                    }
+                    notifyMembersChanged()
+                }
+
+                is Rlt.Failed -> {
+                    if (rlt.error is RoomCantKickAntiKickError) {
+                        CommonDialog.Builder()
+                            .message(rlt.error.msg)
+                            .setShowDefaultCancel(false)
+                            .build()
+                            .show(childFragmentManager)
+                    } else {
+                        showFailedToast(rlt)
+                    }
+                }
+            }
+        }
+    }
+
+    override fun onFollowClick(uid: Long) {
+        super.onFollowClick(uid)
+        val followed = followedMap[uid] ?: return
+        if (followed) {
+            unfollowUser(uid)
+            reportBtnClick(RoomInfoStatEvent.Btn.UN_FOLLOWING)
+        } else {
+            followUser(uid)
+            reportBtnClick(RoomInfoStatEvent.Btn.FOLLOWING)
+        }
+    }
+
+    override fun onReportClick(uid: Long) {
+        super.onReportClick(uid)
+        UserProtectModule.showReportUserDialog(uid, ReportFrom.ROOM_MEMBER, ReportType.USER_INFO)
+    }
+
+    override fun isFollowed(uid: Long): Boolean {
+        if (followedMap.containsKey(uid)) {
+            return followedMap[uid] ?: false
+        }
+
+        followViewModel?.isUserFollowed(uid)
+        return false
+    }
+
+    override fun isRoomOwner(uid: Long): Boolean {
+        return memberViewModel.isRoomOwner(uid)
+    }
+
+    override fun isRoomAdmin(uid: Long): Boolean {
+        return memberViewModel.isRoomAdmin(uid)
+    }
+
+    override fun getMemberInfo(uid: Long, callback: (UserInfo?) -> Unit) {
+        memberViewModel.getRoomMemberInfo(uid).observe(viewLifecycleOwner) { memberRlt ->
+            when(memberRlt) {
+                is Rlt.Success -> {
+                    callback(memberRlt.data)
+                    //更新members
+                    val indexOfMember = members.indexOfFirst { it.uid == uid }
+                    members[indexOfMember] = memberRlt.data
+                }
+                is Rlt.Failed -> {
+                    callback(null)
+                }
+            }
+        }
+    }
+
+    override fun getMemberRole(uid: Long): MemberRoomRole {
+        return memberViewModel.getRoomRole(uid)
+    }
+
+    private fun updateMemberCount(count: Int) {
+        binding.memberCount.text =
+            getCompatString(R.string.room_online_member_count, count)
+    }
+
+    private fun followUser(uid: Long) {
+        followViewModel?.followUser(
+            uid,
+            FollowOpFrom.ROOM_DETAIL,
+            followInRoom = App.instance.mediaManager.getJoinedMediaRoomId()
+        )?.observe(viewLifecycleOwner) {
+            showFailedToast(it)
+        }
+    }
+
+    private fun unfollowUser(uid: Long) {
+        followViewModel?.unFollowUser(uid, FollowOpFrom.ROOM_DETAIL)?.observe(viewLifecycleOwner) {
+            showFailedToast(it)
+        }
+    }
+
+    private fun search() {
+        val keyword = binding.searchEditText.text.toString().trim()
+        if (keyword.isEmpty()) {
+            showToast(getCompatString(APP_R.string.common_input_empty))
+            return
+        }
+
+        binding.searchCancel.visibility = View.VISIBLE
+        val resultList = members.filter {
+            it.containsKeywordBySearch(keyword)
+        }
+        if (resultList.isEmpty()) {
+            showSearchEmpty()
+            return
+        }
+        adapter.submitList(resultList)
+    }
+
+    private fun finishSearch() {
+        binding.searchCancel.visibility = View.GONE
+        adapter.submitList(members)
+    }
+
+    private fun showSearchEmpty() {
+        val resultList = mutableListOf<RoomData>()
+        resultList.add(RoomMemberSearchEmptyData)
+        adapter.submitList(resultList)
+    }
+}

+ 19 - 17
module/room/src/main/java/com/adealink/weparty/room/attr/setting/RoomSettingFragment.kt → module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomSettingFragment.kt

@@ -1,4 +1,4 @@
-package com.adealink.weparty.room.attr.setting
+package com.adealink.weparty.room.attr.info
 
 import android.app.Activity
 import android.os.Bundle
@@ -12,7 +12,6 @@ import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
-import com.adealink.frame.data.json.toJsonErrorNull
 import com.adealink.frame.ext.safeSetSpan
 import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.view.viewBinding
@@ -73,6 +72,7 @@ import com.adealink.weparty.room.theme.RoomThemePanelFragment
 import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
 import com.adealink.weparty.module.setting.Setting
 import com.adealink.frame.util.onClick
+import com.adealink.weparty.commonui.BaseFragment
 import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.commonui.widget.CommonBottomListDialog
 import com.adealink.weparty.commonui.widget.CommonBottomListItem
@@ -81,13 +81,17 @@ import com.adealink.weparty.module.profile.data.GifFreeTimeType
 import com.adealink.weparty.module.theme.ThemeModule
 import com.adealink.weparty.module.youtube.IYoutubeService
 import com.adealink.weparty.module.youtube.YoutubeModule
+import com.adealink.weparty.room.attr.setting.RoomChatSwitchFragment
+import com.adealink.weparty.room.attr.setting.RoomEffectSwitchDialog
+import com.adealink.weparty.room.attr.setting.RoomMicLayoutSelectFragment
+import com.adealink.weparty.room.attr.setting.RoomMicModeSwitchFragment
+import com.adealink.weparty.room.attr.setting.RoomNameEditFragment
+import com.adealink.weparty.room.attr.setting.RoomNoticeEditFragment
+import com.adealink.weparty.room.attr.setting.RoomOnMicModeSwitchFragment
 import com.adealink.weparty.room.constant.ROOM_MIC_MODE_SEAT_20
 import com.adealink.weparty.room.data.GetVipMicConfigInfoRes
 
-/**
- * Created by sunxiaodong on 2021/6/24.
- */
-class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting) {
+class RoomSettingFragment : BaseFragment(R.layout.fragment_room_setting) {
 
     companion object {
         private const val TAG = "RoomSettingFragment"
@@ -95,8 +99,6 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
         private val MAX_HEIGHT = (DisplayUtil.getScreenHeight() * 0.8f).toInt()
     }
 
-    override val fgTag: String = TAG
-
     private val binding by viewBinding(FragmentRoomSettingBinding::bind)
     private val attrViewModel by activityViewModels<RoomAttrViewModel> { RoomViewModelFactory() }
     private val chatMessageViewModel by viewModels<ChatMessageViewModel> { RoomViewModelFactory() }
@@ -260,12 +262,12 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
                     }
                     ?.show(parentFragmentManager)
                 RoomSettingStatEvent.reportBtnClick(RoomSettingStatEvent.Btn.ROOM_MUSIC)
-                dismiss()
+//                dismiss()
             }
         }
         binding.themeItem.setOnClickListener {
             showDialogFragment<RoomThemePanelFragment>(parentFragmentManager)
-            dismiss()
+//            dismiss()
         }
         binding.lockRoomItem.setOnClickListener {
             val setPassword = attrViewModel.getJoinedRoomInfo()?.setPassword == true
@@ -273,19 +275,19 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
                 showUnlockMenu()
             } else {
                 showSetRoomPasswordDialog()
-                dismiss()
+//                dismiss()
             }
         }
         binding.roomAdminItem.setOnClickListener {
             showDialogFragment<RoomAdminListFragment>(parentFragmentManager)
-            dismiss()
+//            dismiss()
         }
         if (!memberViewModel.isIAmRoomOwner() && !RoomAdminPermissionSetting.getAdminPermission(AdminPermissionSetting.MIC_MODE)) {
             binding.micLayoutSwitchLayout.gone()
         }
         binding.micLayoutSwitchLayout.setOnClickListener {
             showDialogFragment<RoomMicLayoutSelectFragment>(parentFragmentManager)
-            dismiss()
+//            dismiss()
         }
         binding.effectSwitchLayout.setOnClickListener {
             showDialogFragment<RoomEffectSwitchDialog>(parentFragmentManager)
@@ -294,7 +296,7 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
             chatMessageViewModel.clearRoomChat().observe(viewLifecycleOwner) {
                 when (it) {
                     is Rlt.Success -> {
-                        dismiss()
+//                        dismiss()
                     }
 
                     else -> {
@@ -307,7 +309,7 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
             chatMessageViewModel.clearRoomChat().observe(viewLifecycleOwner) {
                 when (it) {
                     is Rlt.Success -> {
-                        dismiss()
+//                        dismiss()
                     }
 
                     else -> {
@@ -483,7 +485,7 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
                     when (viewId) {
                         R.id.id_room_change_password -> {
                             showSetRoomPasswordDialog(true)
-                            dismiss()
+//                            dismiss()
                         }
 
                         R.id.id_room_unlock -> {
@@ -572,7 +574,7 @@ class RoomSettingFragment : BottomDialogFragment(R.layout.fragment_room_setting)
                 clickMicModeDot.setAlreadyClick()
                 val act = activity ?: return@setOnClickListener
                 showDialogFragment<RoomMicModeSwitchFragment>(act.supportFragmentManager)
-                dismiss()
+//                dismiss()
             }
             binding.micModeDot.observeDot(this, clickMicModeDot)
         } else {

+ 281 - 0
module/room/src/main/java/com/adealink/weparty/room/attr/info/RoomSummaryFragment.kt

@@ -0,0 +1,281 @@
+package com.adealink.weparty.room.attr.info
+
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.KeyEvent
+import android.view.View
+import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.adealink.frame.aab.util.getCompatString
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.base.fastLazy
+import com.adealink.frame.download.viewmodel.DownloadViewModel
+import com.adealink.frame.mvvm.view.viewBinding
+import com.adealink.frame.util.noOpDelegate
+import com.adealink.weparty.commonui.BaseFragment
+import com.adealink.weparty.commonui.recycleview.adapter.MultiTypeListAdapter
+import com.adealink.weparty.module.medal.MedalModule
+import com.adealink.weparty.module.medal.view.MedalItem
+import com.adealink.weparty.module.profile.data.UserInfo
+import com.adealink.weparty.module.rank.data.MarkItem
+import com.adealink.weparty.module.room.data.MemberRoomRole
+import com.adealink.weparty.module.room.data.RoomData
+import com.adealink.weparty.room.R
+import com.adealink.weparty.room.attr.adapter.RoomMemberSearchEmptyViewBinder
+import com.adealink.weparty.room.attr.data.RoomMemberSearchEmptyData
+import com.adealink.weparty.room.attr.info.stat.RoomInfoStatEvent
+import com.adealink.weparty.room.attr.viewmodel.RoomAttrViewModel
+import com.adealink.weparty.room.databinding.FragmentRoomSummaryBinding
+import com.adealink.weparty.room.diff.RoomDataDiffUtil
+import com.adealink.weparty.room.member.listener.IMemberMedalListener
+import com.adealink.weparty.room.member.listener.IMemberOperaListener
+import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
+import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
+import com.qmuiteam.qmui.widget.util.QMUIKeyboardHelper
+
+
+// TODO: zhangfei  
+class RoomSummaryFragment : BaseFragment(R.layout.fragment_room_summary),
+    IMemberOperaListener, 
+    IMemberMedalListener {
+
+    companion object {
+        const val TAG = "RoomSummaryFragment"
+    }
+
+    private val binding by viewBinding(FragmentRoomSummaryBinding::bind)
+    private val adapter by fastLazy { MultiTypeListAdapter(RoomDataDiffUtil()) }
+    private val memberViewModel by viewModels<RoomMemberViewModel> { RoomViewModelFactory() }
+    private val attrViewModel by viewModels<RoomAttrViewModel> { RoomViewModelFactory() }
+    private val medalViewModel by fastLazy { MedalModule.getMedalViewModel(requireActivity()) }
+    private val downloadViewModel by viewModels<DownloadViewModel>()
+    private var members = mutableListOf<UserInfo>()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        RoomInfoStatEvent.reportShow()
+    }
+
+    override fun initViews() {
+        super.initViews()
+        updateRoomInfo()
+        binding.memberList.layoutManager =
+            LinearLayoutManager(context, RecyclerView.VERTICAL, false)
+//        adapter.register(MemberDetailInfoViewBinder(this, this, this))
+        adapter.register(RoomMemberSearchEmptyViewBinder())
+        binding.memberList.adapter = adapter
+        binding.searchEditText.setOnKeyListener(object : View.OnKeyListener {
+
+            override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean {
+                if (keyCode == KeyEvent.KEYCODE_ENTER && event.action == KeyEvent.ACTION_UP) {
+                    QMUIKeyboardHelper.hideKeyboard(v)
+                    search()
+                    return true
+                }
+                return false
+            }
+
+        })
+        binding.searchEditText.addTextChangedListener(object : TextWatcher by noOpDelegate() {
+
+            override fun afterTextChanged(s: Editable) {
+                if (s.toString().trim().isEmpty()) {
+                    finishSearch()
+                }
+            }
+
+        })
+        binding.searchCancel.setOnClickListener {
+            binding.searchEditText.setText("")
+        }
+    }
+
+    override fun observeViewModel() {
+        super.observeViewModel()
+        attrViewModel.joinedRoomInfoLD.observe(viewLifecycleOwner) {
+            updateRoomInfo()
+        }
+        memberViewModel.rankBoardRoomMembersLD.observe(viewLifecycleOwner) { rlt ->
+            when (rlt) {
+                is Rlt.Success -> {
+                    val userInfos = rlt.data
+                    this.members.clear()
+//                    this.members.addAll(userInfos.map { RoomMember(it) })
+                    notifyMembersChanged()
+                }
+
+                else -> {}
+            }
+        }
+    }
+
+    private fun notifyMembersChanged() {
+        updateMemberCount(members.size)
+        adapter.submitList(members)
+    }
+
+    override fun loadData() {
+        super.loadData()
+        memberViewModel.getRankBoardRoomMembers()
+    }
+
+    private fun updateRoomInfo() {
+        attrViewModel.getJoinedRoomInfo()?.let { item ->
+            binding.roomCover.setImageUrl(item.roomCoverUrl)
+            binding.tvRoomName.text = item.roomName
+            binding.tvRoomId.text = getCompatString(R.string.room_attr_room_id, item.roomId)
+        }
+    }
+
+//    override fun onMemberClick(member: UserInfo) {
+//        showDialogFragment<RoomMemberInfoFragment>(childFragmentManager, Bundle().apply {
+//            putLong(Room.Common.EXTRA_UID, member.uid)
+//        })
+//    }
+
+//    override fun onKickOutClick(member: UserInfo) {
+//        GameDialog.Builder()
+//            .message(getCompatString(R.string.room_kick_user_confirm_tips))
+//            .onPositive {
+//                soundManager.playSound(LudoSound.BUTTON)
+//                showLoading()
+//                memberViewModel.kickOutRoom(member.uid).observe(viewLifecycleOwner) { rlt->
+//                    dismissLoading()
+//                    when (rlt) {
+//                        is Rlt.Success -> {
+//                            this.members.find { it.userInfo?.uid == member.uid }?.let { member ->
+//                                this.members.remove(member)
+//                            }
+//                            notifyMembersChanged()
+//                        }
+//
+//                        is Rlt.Failed -> {
+//                            if (rlt.error is RoomCantKickAntiKickError) {
+//                                GameDialog.Builder()
+//                                    .message(rlt.error.msg)
+//                                    .title(getCompatString(APP_R.string.common_tips))
+//                                    .setShowDefaultCancel(false)
+//                                    .build()
+//                                    .show(childFragmentManager)
+//                            } else {
+//                                showFailedToast(rlt)
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//            .onNegative { soundManager.playSound(LudoSound.BUTTON) }
+//            .setShowDefaultCancel(true)
+//            .showTopClosetButton(false)
+//            .show(childFragmentManager)
+//    }
+
+    override fun onMemberClick(member: UserInfo) {
+        TODO("Not yet implemented")
+    }
+
+    override fun onReportClick(uid: Long) {
+        super.onReportClick(uid)
+//        ProfileModule.showReportUserDialog(uid, ReportFrom.ROOM_DETAIL_MEMBER)
+    }
+
+    override fun getMemberRole(uid: Long): MemberRoomRole {
+        TODO("Not yet implemented")
+    }
+
+    override fun isRoomOwner(uid: Long): Boolean {
+        return memberViewModel.isRoomOwner(uid)
+    }
+
+    override fun isRoomAdmin(uid: Long): Boolean {
+        return memberViewModel.isRoomAdmin(uid)
+    }
+
+//    override fun getMemberInfo(uid: Long, callback: (UserInfo?) -> Unit) {
+//        memberViewModel.getRoomMemberInfo(uid).observe(viewLifecycleOwner) {
+//            callback(if (it is Rlt.Success) it.data else null)
+//        }
+//    }
+
+    private fun updateMemberCount(count: Int) {
+        binding.memberCount.text =
+            getCompatString(R.string.room_online_member_count, count)
+    }
+
+    private fun search() {
+//        val keyword = binding.searchEditText.text.toString().trim()
+//        if (keyword.isEmpty()) {
+//            showToast(getCompatString(APP_R.string.common_input_empty))
+//            return
+//        }
+//
+//        binding.searchCancel.visibility = View.VISIBLE
+//        val resultList = members.filter {
+//            val userInfo = it.userInfo ?: return@filter false
+//            userInfo.uid.toString() == keyword || userInfo.goodIdInfo?.goodId?.toString()
+//                ?.equals(keyword) == true
+//        }
+//        if (resultList.isEmpty()) {
+//            showSearchEmpty()
+//            return
+//        }
+//        adapter.submitList(resultList)
+    }
+
+    private fun finishSearch() {
+        binding.searchCancel.visibility = View.GONE
+        adapter.submitList(members)
+    }
+
+    private fun showSearchEmpty() {
+        val resultList = mutableListOf<RoomData>()
+        resultList.add(RoomMemberSearchEmptyData)
+        adapter.submitList(resultList)
+    }
+
+//    override fun getMedalList(
+//        vipLevel: Int,
+//        medalIds: List<Long>,
+//        callback: (List<MedalItem>?) -> Unit
+//    ) {
+//        if (!isViewBindingValid()) {
+//            callback.invoke(null)
+//            return
+//        }
+//        medalViewModel?.getUserProfileMedalList(vipLevel, medalIds)?.observe(viewLifecycleOwner) {
+//            callback.invoke(it)
+//        }
+//    }
+//
+//    override fun downloadResource(
+//        url: String,
+//        priority: TaskPriority,
+//        callback: (path: String?) -> Unit
+//    ) {
+//        val levelPath = FilePath.levelPath
+//        if (levelPath.isNullOrEmpty()) {
+//            callback(null)
+//            return
+//        }
+//
+//        downloadViewModel.downloadResource(levelPath, url, priority)
+//            .observe(viewLifecycleOwner) {
+//                callback(it)
+//            }
+//    }
+
+    override fun getMedalList(userInfo: UserInfo, callback: (List<MedalItem>?) -> Unit) {
+        TODO("Not yet implemented")
+    }
+//
+//    override fun getMedalList(memberInfo: UserInfo, callback: (List<MedalItem>?) -> Unit) {
+//        TODO("Not yet implemented")
+//    }
+
+    override fun getUserProfileMarkList(uid: Long, goodsList: List<Long>?, callback: (List<MarkItem>?) -> Unit) {
+        TODO("Not yet implemented")
+    }
+
+}

+ 0 - 1
module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicFactory.kt

@@ -23,7 +23,6 @@ import com.adealink.weparty.room.game.RoomGameView
 import com.adealink.weparty.room.game.gamestate.GameEntranceStateView
 import com.adealink.weparty.room.gift.widget.StaticGiftEffectLayout
 import com.adealink.weparty.room.member.widget.RoomOnlineMemberDragView
-import com.adealink.weparty.room.member.widget.RoomOnlineMemberView
 import com.adealink.weparty.room.miccharmpk.MicCharmPKView
 import com.adealink.weparty.room.music.MusicView
 import com.adealink.weparty.room.rank.comp.RankEntranceView

+ 3 - 1
module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomDynamicLayer.kt

@@ -12,7 +12,7 @@ val CHAT_ROOM_BASE_LAYER = intArrayOf(
     R.id.id_chat_room_task_view,
     R.id.id_chat_room_betting_pk_view,
     R.id.id_chat_room_gift_combo_view,
-    R.id.id_chat_room_online_member_view,
+
     R.id.id_chat_room_gift_notice_view,
     R.id.id_chat_room_car_edge_flash_effect_view,
     R.id.id_chat_room_car_effect_view,
@@ -24,6 +24,8 @@ val CHAT_ROOM_BASE_LAYER = intArrayOf(
     R.id.id_chat_room_reward_view,
     R.id.id_chat_room_gift_falling_down_view,
     R.id.id_chat_room_headline_view,
+
+    R.id.id_chat_room_online_member_view,
 )
 
 

+ 0 - 5
module/room/src/main/java/com/adealink/weparty/room/chatroom/page/chat/ChatRoomPageFragment.kt

@@ -24,15 +24,12 @@ import com.adealink.frame.room.data.LeaveRoomReason
 import com.adealink.frame.room.data.TAG_ROOM
 import com.adealink.frame.statistics.CommonEventValue
 import com.adealink.weparty.commonui.BaseFragment
-import com.adealink.weparty.commonui.dialogfragment.showDialogFragment
 import com.adealink.weparty.commonui.ext.dp
 import com.adealink.weparty.commonui.ext.safeRequestLayout
 import com.adealink.weparty.commonui.layout.DynamicLayers
-import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.weparty.commonui.widget.SpreadLinearLayout
 import com.adealink.weparty.module.profile.ProfileModule
 import com.adealink.weparty.module.room.Room
-import com.adealink.weparty.module.room.data.MemberRoomRole
 import com.adealink.weparty.module.room.data.MicOperate
 import com.adealink.weparty.module.room.data.MicSeatsTemplate
 import com.adealink.weparty.module.room.sdk.data.MicIndex
@@ -40,7 +37,6 @@ import com.adealink.weparty.module.room.sdk.data.RoomType
 import com.adealink.weparty.room.R
 import com.adealink.weparty.room.activity.ActivityComp
 import com.adealink.weparty.room.attr.info.RoomInfoFragment
-import com.adealink.weparty.room.attr.setting.RoomSettingFragment
 import com.adealink.weparty.room.bettingpk.BettingPkComp
 import com.adealink.weparty.room.car.RoomCarComp
 import com.adealink.weparty.room.chat.ChatMessageFragment
@@ -62,7 +58,6 @@ import com.adealink.weparty.room.gift.view.RoomGiftComp
 import com.adealink.weparty.room.gift.view.RoomSendGiftComboComp
 import com.adealink.weparty.room.giftwish.GiftWishComp
 import com.adealink.weparty.room.headline.HeadlineComp
-import com.adealink.weparty.room.invite.RoomInvitedBellComp
 import com.adealink.weparty.room.level.LevelComp
 import com.adealink.weparty.room.member.comp.RoomOnlineMemberComp
 import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel

+ 7 - 32
module/room/src/main/java/com/adealink/weparty/room/create/RoomCreateActivity.kt

@@ -1,30 +1,24 @@
 package com.adealink.weparty.room.create
 
-import android.text.Editable
-import android.text.TextWatcher
-import android.view.View
 import androidx.activity.viewModels
 import com.adealink.frame.aab.util.getCompatString
 import com.adealink.frame.base.Rlt
 import com.adealink.frame.base.fastLazy
-import com.adealink.weparty.commonui.BaseActivity
-import com.adealink.weparty.commonui.toast.util.showFailedToast
-import com.adealink.weparty.commonui.toast.util.showToast
 import com.adealink.frame.coroutine.dispatcher.Dispatcher
-import com.adealink.weparty.imageselect.SelectImageLifecycleObserver
-import com.adealink.weparty.imageselect.model.MediaInfo
-import com.adealink.weparty.imageselect.model.MediaType
-import com.adealink.frame.log.Log
 import com.adealink.frame.mvvm.view.viewBinding
 import com.adealink.frame.router.Router
 import com.adealink.frame.router.annotation.RouterUri
 import com.adealink.frame.statistics.CommonEventValue
 import com.adealink.frame.util.deleteFiles
-import com.adealink.frame.util.noOpDelegate
-import com.adealink.weparty.room.R
+import com.adealink.weparty.commonui.BaseActivity
+import com.adealink.weparty.commonui.toast.util.showFailedToast
+import com.adealink.weparty.commonui.toast.util.showToast
+import com.adealink.weparty.imageselect.SelectImageLifecycleObserver
+import com.adealink.weparty.imageselect.model.MediaInfo
+import com.adealink.weparty.imageselect.model.MediaType
 import com.adealink.weparty.module.room.Room
+import com.adealink.weparty.room.R
 import com.adealink.weparty.room.constant.RoomAlreadyCreate
-import com.adealink.weparty.room.constant.TAG_ROOM_CREATE
 import com.adealink.weparty.room.create.stat.RoomCreateStatEvent
 import com.adealink.weparty.room.create.viewmodel.RoomCreateViewModel
 import com.adealink.weparty.room.data.EnterRoomInfo
@@ -34,9 +28,6 @@ import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
 import com.adealink.weparty.stat.CreateRoomStatEvent
 import com.adealink.weparty.R as APP_R
 
-/**
- * Created by sunxiaodong on 2021/4/18.
- */
 @RouterUri(path = [Room.Create.PATH], desc = "房间创建")
 class RoomCreateActivity : BaseActivity() {
 
@@ -78,21 +69,6 @@ class RoomCreateActivity : BaseActivity() {
         binding.roomCover.setOnClickListener {
             selectImageObserver.launch()
         }
-        binding.roomNameEdit.addTextChangedListener(object : TextWatcher by noOpDelegate() {
-
-            override fun afterTextChanged(s: Editable) {
-                if (s.isEmpty()) {
-                    binding.roomNameEditPenIcon.visibility = View.VISIBLE
-                    binding.roomNameEditNum.visibility = View.INVISIBLE
-                } else {
-                    binding.roomNameEditPenIcon.visibility = View.GONE
-                    binding.roomNameEditNum.visibility = View.VISIBLE
-                    binding.roomNameEditNum.text =
-                        getCompatString(R.string.room_name_edit_num, s.length)
-                }
-            }
-
-        })
         binding.roomCreateBtn.setOnClickListener {
             createRoom()
         }
@@ -111,7 +87,6 @@ class RoomCreateActivity : BaseActivity() {
 
     override fun observeViewModel() {
         roomCreateViewModel.roomCreateLD.observe(this, {
-            Log.logRltD(TAG_ROOM_CREATE, "observeViewModel", it)
             dismissLoading()
             var roomId: Long = 0
             var picUrl = ""

+ 2 - 0
module/room/src/main/java/com/adealink/weparty/room/interceptor/EnterRoomUriInterceptor.kt

@@ -44,6 +44,7 @@ import com.adealink.weparty.room.constant.enterRoomUILoadTime
 import com.adealink.weparty.room.constant.markEnterRoomTime
 import com.adealink.weparty.room.data.EnterRoomInfo
 import com.adealink.weparty.room.data.JoinRoomFrom
+import com.adealink.weparty.room.member.manager.onlineMemberManager
 import com.adealink.weparty.room.sdk.data.RoomJoinNeedPwdError
 import com.adealink.weparty.room.sdk.data.RoomJoinPwdError
 import com.adealink.weparty.room.sdk.service.roomService
@@ -184,6 +185,7 @@ class EnterRoomUriInterceptor : UriInterceptor {
             .build()
         progressDialog.show(activity.supportFragmentManager, ProgressDialog.TAG)
         EnterEffectModule.subscribeNotify()
+        onlineMemberManager.subscribeNotify()
         val startTime = SystemClock.elapsedRealtime()
         val result = roomService.joinController.joinRoom(
             JoinRoomReq(

+ 16 - 17
module/room/src/main/java/com/adealink/weparty/room/member/comp/RoomOnlineMemberComp.kt

@@ -7,12 +7,12 @@ import com.adealink.frame.mvvm.viewmodel.viewModels
 import com.adealink.weparty.commonui.dialogfragment.showDialogFragment
 import com.adealink.weparty.commonui.layout.DynamicLayers
 import com.adealink.weparty.commonui.layout.IDynamicView
-import com.adealink.weparty.module.entereffect.EnterEffectModule
 import com.adealink.weparty.module.room.Room
 import com.adealink.weparty.room.R
+import com.adealink.weparty.room.attr.info.RoomDetailInfoFragment
 import com.adealink.weparty.room.base.BaseRoomComp
 import com.adealink.weparty.room.member.RoomMemberInfoFragment
-import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
+import com.adealink.weparty.room.member.viewmodel.RoomOnlineMemberViewModel
 import com.adealink.weparty.room.member.widget.RoomOnlineMemberDragView
 import com.adealink.weparty.room.member.widget.RoomOnlineMemberView
 import com.adealink.weparty.room.viewmodel.RoomViewModelFactory
@@ -29,38 +29,33 @@ class RoomOnlineMemberComp(
                     override fun onAvatarClick(uid: Long) {
                         this@RoomOnlineMemberComp.onAvatarClick(uid)
                     }
+
+                    override fun onMemberCountClick() {
+                        this@RoomOnlineMemberComp.onMemberCountClick()
+                    }
                 })
             }
         }
     }
 
-    private val memberViewModel by viewModels<RoomMemberViewModel> { RoomViewModelFactory() }
-    private val enterEffectViewModel by fastLazy {
-        EnterEffectModule.getEnterEffectViewModel(viewModelStoreOwner)
-    }
+    private val onlineMemberViewModel by viewModels<RoomOnlineMemberViewModel> { RoomViewModelFactory() }
 
     override fun loadData() {
         super.loadData()
         onlineMemberView.view {
             val view = it.getOnlineMemberView()
-            view.setMemberCount(memberViewModel.getOnlineMemberCount())
-        }
-        memberViewModel.getRoomMembers().observe(viewLifecycleOwner) { members ->
-            onlineMemberView.view {
-                val view = it.getOnlineMemberView()
-                view.addMembers(members)
-            }
+            view.setMemberCount(onlineMemberViewModel.getOnlineMemberCount())
         }
+        onlineMemberViewModel.getOnlineMembers()
     }
 
     override fun observeViewModel() {
-        enterEffectViewModel?.roomUserEnterNotifyLD?.observeWithoutCache(viewLifecycleOwner) { notify ->
-            val member = notify.roomUserInfo?.userInfo ?: return@observeWithoutCache
+        onlineMemberViewModel.onlineMembersLD.observe(viewLifecycleOwner) { userList ->
             onlineMemberView.view { view ->
-                view.getOnlineMemberView().addMember(member)
+                view.getOnlineMemberView().setMembers(userList)
             }
         }
-        memberViewModel.onlineMemberCountLD.observe(viewLifecycleOwner) {
+        onlineMemberViewModel.roomMemberCountLD.observe(viewLifecycleOwner) {
             onlineMemberView.view { view ->
                 view.getOnlineMemberView().setMemberCount(it)
             }
@@ -72,4 +67,8 @@ class RoomOnlineMemberComp(
             putLong(Room.Common.EXTRA_UID, uid)
         })
     }
+
+    private fun onMemberCountClick() {
+        showDialogFragment<RoomDetailInfoFragment>(fragmentManager)
+    }
 }

+ 2 - 1
module/room/src/main/java/com/adealink/weparty/room/member/listener/IMemberMedalListener.kt

@@ -1,9 +1,10 @@
 package com.adealink.weparty.room.member.listener
 
 import com.adealink.weparty.module.medal.view.MedalItem
+import com.adealink.weparty.module.profile.data.UserInfo
 import com.adealink.weparty.module.rank.data.MarkItem
 
 interface IMemberMedalListener {
-    fun getMedalList(userInfo: com.adealink.weparty.module.profile.data.UserInfo, callback: (List<MedalItem>?) -> Unit)
+    fun getMedalList(userInfo: UserInfo, callback: (List<MedalItem>?) -> Unit)
     fun getUserProfileMarkList(uid: Long,goodsList: List<Long>?, callback: (List<MarkItem>?) -> Unit)
 }

+ 9 - 0
module/room/src/main/java/com/adealink/weparty/room/member/listener/IOnlineMemberListener.kt

@@ -0,0 +1,9 @@
+package com.adealink.weparty.room.member.listener
+
+import com.adealink.frame.frame.IListener
+import com.adealink.weparty.module.profile.data.UserInfo
+
+
+interface IOnlineMemberListener : IListener {
+    fun onOnlineMembersChanged(members: List<UserInfo?>)
+}

+ 11 - 0
module/room/src/main/java/com/adealink/weparty/room/member/manager/IOnlineMemberManager.kt

@@ -0,0 +1,11 @@
+package com.adealink.weparty.room.member.manager
+
+import com.adealink.frame.frame.IBaseFrame
+import com.adealink.weparty.room.member.listener.IOnlineMemberListener
+
+interface IOnlineMemberManager : IBaseFrame<IOnlineMemberListener> {
+
+    fun subscribeNotify()
+
+    fun getOnlineMembers()
+}

+ 100 - 0
module/room/src/main/java/com/adealink/weparty/room/member/manager/OnlineMemberManager.kt

@@ -0,0 +1,100 @@
+package com.adealink.weparty.room.member.manager
+
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.frame.BaseFrame
+import com.adealink.frame.log.Log
+import com.adealink.frame.network.ISocketNotify
+import com.adealink.frame.room.data.TAG_ROOM_ONLINE_MEMBER
+import com.adealink.weparty.App
+import com.adealink.weparty.module.entereffect.data.ServerRoomUserEnterNotify
+import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.module.room.RoomModule
+import com.adealink.weparty.module.room.data.MicSeatInfo
+import com.adealink.weparty.room.member.listener.IOnlineMemberListener
+import com.adealink.weparty.room.sdk.listener.IWPSeatListener
+import com.adealink.weparty.room.sdk.service.roomService
+import kotlinx.coroutines.launch
+import java.util.LinkedList
+
+val onlineMemberManager: IOnlineMemberManager by lazy { OnlineMemberManager() }
+
+class OnlineMemberManager : BaseFrame<IOnlineMemberListener>(), IOnlineMemberManager, IWPSeatListener {
+
+    private val onlineUids = LinkedList<Long>()
+    private var onMicUids: List<Long>? = null
+
+    private val roomUserEnterNotify = object : ISocketNotify<ServerRoomUserEnterNotify> {
+
+        override val uri: String = "AUDIENCE_ENTER_ROOM_NOTIFY"
+
+        override fun needHandle(data: ServerRoomUserEnterNotify?): Boolean {
+            return data != null && data.roomId == RoomModule.getJoinedRoomId()
+        }
+
+        override fun onNotify(data: ServerRoomUserEnterNotify) {
+            Log.d(TAG_ROOM_ONLINE_MEMBER, "onNotify,$data")
+            handleRoomUserEnterNotify(data)
+        }
+    }
+
+    private fun handleRoomUserEnterNotify(data: ServerRoomUserEnterNotify) {
+        launch {
+            val enterUser = data.enterUser ?: return@launch
+            addOnlineMembers(enterUser.keys.toList())
+        }
+    }
+
+    override fun onMicSeatsChanged(micSeatsInfo: Map<Int, MicSeatInfo>) {
+        val onMicUids = micSeatsInfo.values.map { it.micUid }
+        this.onMicUids = onMicUids
+        notifyOnlineMembersChanged()
+    }
+
+    override fun subscribeNotify() {
+        App.instance.networkService.subscribeNotify(roomUserEnterNotify)
+        roomService.seatController.addListener(this)
+    }
+
+    override fun getOnlineMembers() {
+        launch {
+            // TODO: zhangfei 截取前50个
+            when (val rlt = roomService.memberController.getRankBoardMembers()) {
+                is Rlt.Failed -> {
+                    //Ntd.
+                }
+
+                is Rlt.Success -> {
+                    val uids = rlt.data.map { it.uid }
+                    addOnlineMembers(uids)
+                }
+            }
+        }
+    }
+
+    private fun addOnlineMembers(uids: List<Long>) {
+        launch {
+            onlineUids.removeAll(uids.toSet())
+            uids.onEach {
+                onlineUids.addFirst(it)
+            }
+            notifyOnlineMembersChanged()
+        }
+    }
+
+    private fun notifyOnlineMembersChanged() {
+        launch {
+            val onlineUids = onlineUids.toList()
+            val onMicUids = this@OnlineMemberManager.onMicUids?.toSet() ?: emptySet()
+            //移除在麦用户
+            val reqUids = onlineUids.filter { !onMicUids.contains(it) }
+
+            val userInfoMap = (ProfileModule.getUsersInfoByUid(reqUids.toSet(), true) as? Rlt.Success)?.data
+            val onlineUserInfoList = reqUids.map { uid ->
+                userInfoMap?.get(uid)
+            }
+            dispatch {
+                it.onOnlineMembersChanged(onlineUserInfoList)
+            }
+        }
+    }
+}

+ 47 - 0
module/room/src/main/java/com/adealink/weparty/room/member/viewmodel/RoomOnlineMemberViewModel.kt

@@ -0,0 +1,47 @@
+package com.adealink.weparty.room.member.viewmodel
+
+import androidx.lifecycle.MutableLiveData
+import com.adealink.frame.base.Rlt
+import com.adealink.frame.mvvm.viewmodel.BaseViewModel
+import com.adealink.weparty.module.profile.ProfileModule
+import com.adealink.weparty.module.profile.data.UserInfo
+import com.adealink.weparty.room.member.listener.IOnlineMemberListener
+import com.adealink.weparty.room.member.manager.onlineMemberManager
+import com.adealink.weparty.room.sdk.listener.IWPMemberListener
+import com.adealink.weparty.room.sdk.service.roomService
+import kotlinx.coroutines.launch
+import java.util.LinkedList
+
+class RoomOnlineMemberViewModel : BaseViewModel(), IOnlineMemberListener, IWPMemberListener {
+
+    val onlineMembersLD = MutableLiveData<List<UserInfo?>>()
+    val roomMemberCountLD = MutableLiveData<Long>()
+
+    private val memberController by lazy { roomService.memberController }
+
+    init {
+        onlineMemberManager.addListener(this)
+        memberController.addListener(this)
+    }
+
+    override fun onCleared() {
+        super.onCleared()
+        onlineMemberManager.removeListener(this)
+    }
+
+    fun getOnlineMembers() {
+        onlineMemberManager.getOnlineMembers()
+    }
+
+    fun getOnlineMemberCount(): Long {
+        return memberController.getOnlineMemberCount()
+    }
+
+    override fun onMemberCountChanged(count: Long) {
+        roomMemberCountLD.postValue(count)
+    }
+
+    override fun onOnlineMembersChanged(members: List<UserInfo?>) {
+        onlineMembersLD.postValue(members)
+    }
+}

+ 9 - 15
module/room/src/main/java/com/adealink/weparty/room/member/widget/RoomOnlineMemberDragView.kt

@@ -4,7 +4,6 @@ import android.content.Context
 import android.util.AttributeSet
 import android.view.LayoutInflater
 import android.view.MotionEvent
-import androidx.core.view.isVisible
 import com.adealink.frame.log.Log
 import com.adealink.weparty.commonui.drag.BaseDragView
 import com.adealink.weparty.commonui.drag.DragTouchEventDelegate
@@ -21,17 +20,14 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
 
     private val binding = LayoutRoomOnlineMemberBinding.inflate(LayoutInflater.from(context), this)
     private var isDragging = false
+    override var resetToLastLocationAfterLayout = false
 
     init {
         initView()
     }
 
-    override fun resetToLastLocationAfterLayout(reset: Boolean) {
-        super.resetToLastLocationAfterLayout(reset)
-    }
-
     override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
-        Log.d(TAG_DRAG_VIEW, "onInterceptTouchEvent(RoomBettingPkDragView), isDragging: $isDragging, ${ev?.let { MotionEvent.actionToString(it.action) }}")
+        Log.d(TAG_DRAG_VIEW, "onInterceptTouchEvent(RoomOnlineMemberDragView), isDragging: $isDragging, ${ev?.let { MotionEvent.actionToString(it.action) }}")
         if (isDragging) {
             return true
         }
@@ -39,7 +35,7 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
     }
 
     override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
-        Log.d(TAG_DRAG_VIEW, "dispatchTouchEvent(RoomBettingPkDragView), ${ev?.let { MotionEvent.actionToString(it.action) }}")
+        Log.d(TAG_DRAG_VIEW, "dispatchTouchEvent(RoomOnlineMemberDragView), ${ev?.let { MotionEvent.actionToString(it.action) }}")
         if (ev?.action == MotionEvent.ACTION_DOWN || ev?.action == MotionEvent.ACTION_UP) {
             isDragging = false
             binding.root.parent.requestDisallowInterceptTouchEvent(true)
@@ -52,13 +48,13 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
         binding.ivOnlineMember.touchDelegate =
             GestureDetectDelegate(binding.ivOnlineMember, object : SimpleSafeOnGestureListener {
                 override fun onDown(e: MotionEvent): Boolean {
-                    Log.d(TAG_DRAG_VIEW, "onDown(RoomBettingPkDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
+                    Log.d(TAG_DRAG_VIEW, "onDown(RoomOnlineMemberDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
                     return true
                 }
 
 
                 override fun onSingleTapUp(e: MotionEvent): Boolean {
-                    Log.d(TAG_DRAG_VIEW, "onSingleTapUp(RoomBettingPkDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
+                    Log.d(TAG_DRAG_VIEW, "onSingleTapUp(RoomOnlineMemberDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
 //                    return onWaitingClick?.let {
 //                        it.invoke()
 //                        true
@@ -67,7 +63,7 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
                 }
 
                 override fun onLongPress(e: MotionEvent) {
-                    Log.d(TAG_DRAG_VIEW, "onLongPress(RoomBettingPkDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
+                    Log.d(TAG_DRAG_VIEW, "onLongPress(RoomOnlineMemberDragView.ivWaiting), ${MotionEvent.actionToString(e.action)}")
                     isDragging = true
                     binding.root.parent.requestDisallowInterceptTouchEvent(false)
                     onLongPressCallback(e)
@@ -77,10 +73,6 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
     }
 
     override fun isDraggable(): Boolean {
-        if (binding.ivOnlineMember.isVisible) {
-            //Waiting状态
-            return true
-        }
         if (!binding.ivOnlineMember.isExpand()) {
             //控件折叠状态
             return true
@@ -94,6 +86,8 @@ class RoomOnlineMemberDragView @JvmOverloads constructor(
     }
 
     private fun onLongPressCallback(e: MotionEvent) {
-        (touchDelegate as? DragTouchEventDelegate)?.onLongPressCallback(e)
+        if (isDraggable()) {
+            (touchDelegate as? DragTouchEventDelegate)?.onLongPressCallback(e)
+        }
     }
 }

+ 17 - 7
module/room/src/main/java/com/adealink/weparty/room/member/widget/RoomOnlineMemberView.kt

@@ -40,14 +40,10 @@ class RoomOnlineMemberView @JvmOverloads constructor(
         adapter.register(RoomOnlineMemberItemViewBinder {
             listener?.onAvatarClick(it)
         })
-        binding.rvMembers.adapter = adapter
         binding.rvMembers.layoutManager =
             LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
         binding.rvMembers.addItemDecoration(HorizontalItemDecoration(8f, 0f, 0f))
-        repeat(MAX_MEMBER_COUNT) {
-            onlineMemberList.add(RoomOnlineMemberItemData())
-        }
-        adapter.submitList(onlineMemberList)
+        binding.rvMembers.adapter = adapter
         binding.ivFold.setOnClickListener {
             if (isExpend) {
                 isExpend = false
@@ -59,6 +55,9 @@ class RoomOnlineMemberView @JvmOverloads constructor(
                 binding.rvMembers.show()
             }
         }
+        binding.clMemberCount.setOnClickListener {
+            listener?.onMemberCountClick()
+        }
     }
 
     fun setListener(listener: OnClickListener) {
@@ -76,7 +75,7 @@ class RoomOnlineMemberView @JvmOverloads constructor(
         }
     }
 
-    fun addMembers(members: List<UserInfo>) {
+    fun addMembers(members: List<UserInfo?>) {
         members.reversed().onEach {
             onlineMemberList.removeLast()
             onlineMemberList.addFirst(RoomOnlineMemberItemData(it))
@@ -89,11 +88,21 @@ class RoomOnlineMemberView @JvmOverloads constructor(
         }
     }
 
+    fun setMembers(members: List<UserInfo?>) {
+        onlineMemberList.clear()
+        onlineMemberList.addAll(members.map { RoomOnlineMemberItemData(it) })
+        adapter.submitList(onlineMemberList)
+        if (onlineMemberList.isEmpty()) {
+            binding.rvMembers.gone()
+        } else {
+            binding.rvMembers.show()
+        }
+    }
+
     fun setMemberCount(count: Long) {
         binding.tvMemberCount.text = count.toString()
     }
 
-
     fun isExpand(): Boolean {
         return isExpend
     }
@@ -132,6 +141,7 @@ class RoomOnlineMemberView @JvmOverloads constructor(
 
     interface OnClickListener {
         fun onAvatarClick(uid: Long)
+        fun onMemberCountClick()
     }
 
     companion object {

+ 1 - 11
module/room/src/main/java/com/adealink/weparty/room/playcenter/RoomPlayCenterPanelFragment.kt

@@ -46,7 +46,7 @@ import com.adealink.weparty.module.webview.Web
 import com.adealink.weparty.module.webview.WebViewDialogFragmentBuilder
 import com.adealink.weparty.module.webview.data.OfflineH5GameInfo
 import com.adealink.weparty.room.R
-import com.adealink.weparty.room.attr.setting.RoomSettingFragment
+import com.adealink.weparty.room.attr.info.RoomSettingFragment
 import com.adealink.weparty.room.data.AdminPermissionSetting
 import com.adealink.weparty.room.databinding.FragmentRoomPlayCenterPanelBinding
 import com.adealink.weparty.room.datasource.local.RoomAdminPermissionSetting
@@ -271,16 +271,6 @@ class RoomPlayCenterPanelFragment : BottomDialogFragment(R.layout.fragment_room_
         dismiss()
     }
 
-    private fun showRoomSettingsDialog() {
-        val fragmentActivity = activity ?: return
-        if (isActivityFinishing(fragmentActivity)) {
-            return
-        }
-        showDialogFragment<RoomSettingFragment>(fragmentActivity.supportFragmentManager)
-        dismiss()
-    }
-
-
     private fun showRoomBettingPkDialog() {
         val act = activity ?: return
         Router.getRouterInstance<BaseDialogFragment>(BettingPK.BettingPK.PATH)?.apply {

+ 1 - 1
module/room/src/main/java/com/adealink/weparty/room/sdk/listener/IWPMemberListener.kt

@@ -8,7 +8,7 @@ import com.adealink.weparty.module.room.data.MemberRoomRole
  */
 interface IWPMemberListener : IListener {
 
-    fun onKickOutRoom(kickReason: Long)
+    fun onKickOutRoom(kickReason: Long) {}
 
     /**
      * 在线成员数变化

+ 3 - 0
module/room/src/main/java/com/adealink/weparty/room/viewmodel/RoomViewModelFactory.kt

@@ -14,6 +14,7 @@ import com.adealink.weparty.room.device.viewmodel.RoomDeviceViewModel
 import com.adealink.weparty.room.game.viewmodel.RoomGameViewModel
 import com.adealink.weparty.room.guardtreasure.viewmodel.InviteMemberViewModel
 import com.adealink.weparty.room.member.viewmodel.RoomMemberViewModel
+import com.adealink.weparty.room.member.viewmodel.RoomOnlineMemberViewModel
 import com.adealink.weparty.room.micseat.viewmodel.RoomSeatViewModel
 import com.adealink.weparty.room.playcenter.viewmodel.RoomPlayCenterViewModel
 import com.adealink.weparty.room.roomlist.popular.comp.viewmodel.FloatCountryTabViewModel
@@ -68,6 +69,8 @@ class RoomViewModelFactory : ViewModelProvider.NewInstanceFactory() {
                     CarromFlowViewModel()
                 isAssignableFrom(UnoFlowViewModel::class.java) ->
                     UnoFlowViewModel()
+                isAssignableFrom(RoomOnlineMemberViewModel::class.java) ->
+                    RoomOnlineMemberViewModel()
                 else ->
                     throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}")
             } as T

BIN
module/room/src/main/res/drawable-xhdpi/room_create_camera_ic.png


BIN
module/room/src/main/res/drawable-xhdpi/room_create_input_room_name_ic.png


BIN
module/room/src/main/res/drawable-xhdpi/room_room_create_bg.png


+ 6 - 0
module/room/src/main/res/drawable/room_create_input_bg.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/color_F5F7FA" />
+    <corners android:radius="60dp" />
+</shape>

+ 54 - 68
module/room/src/main/res/layout/activity_room_create.xml

@@ -1,10 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/room_room_create_bg"
     android:fitsSystemWindows="true">
 
     <androidx.constraintlayout.widget.ConstraintLayout
@@ -15,12 +13,12 @@
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
 
-        <ImageView
+        <androidx.appcompat.widget.AppCompatImageView
             android:id="@+id/title_back_btn"
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:layout_marginStart="20dp"
-            android:src="@drawable/common_back_white_fork"
+            android:src="@drawable/commonui_back_black_48_ic"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
@@ -33,7 +31,7 @@
             android:layout_marginEnd="64dp"
             android:gravity="center_horizontal"
             android:text="@string/room_create_title"
-            android:textColor="@color/white"
+            android:textColor="@color/color_222222"
             android:textSize="18sp"
             android:textStyle="bold"
             app:layout_constraintBottom_toBottomOf="parent"
@@ -45,8 +43,8 @@
 
     <com.adealink.weparty.commonui.imageview.AvatarView
         android:id="@+id/room_cover"
-        android:layout_width="160dp"
-        android:layout_height="160dp"
+        android:layout_width="92dp"
+        android:layout_height="92dp"
         android:layout_marginTop="40dp"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
@@ -55,80 +53,68 @@
         app:placeholderImageScaleType="centerCrop"
         app:roundedCornerRadius="12dp" />
 
-    <ImageView
+    <androidx.appcompat.widget.AppCompatImageView
         android:id="@+id/camera_icon"
-        android:layout_width="40dp"
-        android:layout_height="40dp"
-        android:src="@drawable/common_green_camera_ic"
+        android:layout_width="28dp"
+        android:layout_height="28dp"
+        android:src="@drawable/room_create_camera_ic"
         app:layout_constraintBottom_toBottomOf="@id/room_cover"
-        app:layout_constraintEnd_toEndOf="@id/room_cover"
-        app:layout_constraintStart_toStartOf="@id/room_cover"
-        app:layout_constraintTop_toTopOf="@id/room_cover" />
+        app:layout_constraintEnd_toEndOf="@id/room_cover" />
 
     <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/room_name_tip"
+        android:id="@+id/tv_upload_cover_tips"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_marginStart="20dp"
-        android:layout_marginTop="28dp"
-        android:layout_marginEnd="20dp"
-        android:text="@string/room_name"
-        android:textColor="@color/white"
-        android:textSize="16sp"
-        android:textStyle="bold"
+        android:layout_marginHorizontal="24dp"
+        android:layout_marginTop="12dp"
+        android:includeFontPadding="false"
+        android:text="@string/room_create_upload_cover_tips"
+        android:textColor="@color/color_777777"
+        android:textSize="14sp"
+        app:layout_constrainedWidth="true"
+        app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@id/room_cover" />
 
-    <ImageView
-        android:id="@+id/room_name_edit_pen_icon"
-        android:layout_width="20dp"
-        android:layout_height="20dp"
-        android:layout_marginTop="24dp"
-        android:layout_marginEnd="20dp"
-        android:src="@drawable/common_pen_ic"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/room_name_tip" />
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/room_name_edit_num"
-        android:layout_width="38dp"
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_input_room_name"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="24dp"
-        android:layout_marginEnd="20dp"
-        android:textColor="@color/color_66FFFFFF"
-        android:textSize="14sp"
-        android:visibility="invisible"
+        android:layout_marginHorizontal="40dp"
+        android:layout_marginTop="44dp"
+        android:background="@drawable/room_create_input_bg"
+        android:paddingHorizontal="16dp"
+        android:paddingVertical="14dp"
         app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/room_name_tip"
-        tools:text="15/30" />
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/tv_upload_cover_tips">
 
-    <EditText
-        android:id="@+id/room_name_edit"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="24dp"
-        android:background="@color/transparent"
-        android:hint="@string/room_name_edit_hint"
-        android:maxLength="30"
-        android:textColor="@color/white"
-        android:textColorHint="@color/color_80FFFFFF"
-        android:textSize="16sp"
-        android:textStyle="normal"
-        app:layout_constraintEnd_toStartOf="@+id/room_name_edit_num"
-        app:layout_constraintStart_toStartOf="@+id/room_name_tip"
-        app:layout_constraintTop_toTopOf="@+id/room_name_edit_num" />
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/iv_input_name"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:src="@drawable/room_create_input_room_name_ic"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
 
-    <View
-        android:id="@+id/room_name_edit_bottom_line"
-        android:layout_width="0dp"
-        android:layout_height="0.5dp"
-        android:layout_marginStart="20dp"
-        android:layout_marginTop="24dp"
-        android:layout_marginEnd="20dp"
-        android:background="@color/white"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/room_name_edit" />
+        <androidx.appcompat.widget.AppCompatEditText
+            android:id="@+id/room_name_edit"
+            style="@style/CommonEditText"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="16dp"
+            android:background="@color/transparent"
+            android:hint="@string/room_name_edit_hint"
+            android:maxLength="30"
+            android:singleLine="true"
+            android:textSize="14sp"
+            android:textStyle="normal"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/iv_input_name"
+            app:layout_constraintTop_toTopOf="parent" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <com.adealink.weparty.commonui.widget.CommonButton
         android:id="@+id/room_create_btn"

+ 23 - 114
module/room/src/main/res/layout/fragment_room_detail_info.xml

@@ -1,136 +1,45 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:background="@drawable/common_white_top_radius_12_bg">
+    android:background="@drawable/commonui_bottom_list_dialog_bg">
 
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/title"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="15dp"
-        android:background="@drawable/common_white_top_radius_12_bg"
-        android:gravity="center"
-        android:text="@string/room_detail"
-        android:textColor="@color/color_222222"
-        android:textSize="15sp"
-        android:textStyle="bold"
+    <com.adealink.weparty.commonui.widget.CommonTabLayout
+        android:id="@+id/tab_title"
+        android:layout_width="0dp"
+        android:layout_height="48dp"
+        app:indicator_color="@color/color_app_main"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
+        app:layout_constraintTop_toTopOf="parent"
+        app:normal_tab_color="@color/color_FF7AB3BD"
+        app:normal_text_size="16sp"
+        app:selected_tab_color="@color/color_game_normal"
+        app:selected_text_size="18sp"
+        app:tab_mode="fixed"
+        app:tab_type="match_parent" />
 
     <androidx.appcompat.widget.AppCompatImageView
         android:id="@+id/report_iv"
         android:layout_width="28dp"
         android:layout_height="28dp"
-        android:layout_marginEnd="12dp"
-        android:visibility="gone"
-        tools:visibility="visible"
+        android:layout_marginEnd="20dp"
         android:src="@drawable/common_report_gray_28_ic"
-        app:layout_constraintBottom_toBottomOf="@id/title"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@id/title" />
-
-
-
-    <include
-        android:id="@+id/layout_room_info"
-        layout="@layout/item_room_info"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="19dp"
-        android:layout_marginHorizontal="16dp"
-        app:layout_constraintTop_toBottomOf="@id/title" />
-
-    <com.adealink.weparty.module.family.view.FamilyInfoView
-        android:id="@+id/family_info_view"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginHorizontal="16dp"
-        android:layout_marginTop="12dp"
         android:visibility="gone"
-        app:layout_constraintTop_toBottomOf="@+id/layout_room_info"
-        tools:layout_height="60dp"
+        app:layout_constraintBottom_toBottomOf="@id/tab_title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/tab_title"
         tools:visibility="visible" />
 
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/member_count"
+    <androidx.viewpager2.widget.ViewPager2
+        android:id="@+id/vp_content"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingHorizontal="16dp"
-        android:paddingTop="16dp"
-        android:paddingBottom="8dp"
-        android:textColor="@color/color_AAAAAA"
-        android:textSize="13sp"
-        app:layout_constraintTop_toBottomOf="@id/family_info_view" />
-
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/search_layout"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginTop="4dp"
-        android:layout_marginEnd="9dp"
-        android:background="@drawable/common_f5f7fa_radius_20_bg"
-        android:padding="12dp"
-        app:layout_constraintEnd_toStartOf="@+id/search_cancel"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/member_count"
-        app:layout_goneMarginEnd="8dp">
-
-        <androidx.appcompat.widget.AppCompatImageView
-            android:id="@+id/search_icon"
-            android:layout_width="16dp"
-            android:layout_height="16dp"
-            android:src="@drawable/common_search_gray_16_ic"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
-
-        <androidx.appcompat.widget.AppCompatEditText
-            android:id="@+id/search_edit_text"
-            style="@style/RtlTextViewStyle"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="8dp"
-            android:background="@null"
-            android:hint="@string/common_enter_id"
-            android:imeOptions="actionSearch"
-            android:inputType="text"
-            android:singleLine="true"
-            android:textColor="@color/color_222222"
-            android:textColorHint="@color/color_AAAAAA"
-            android:textSize="14sp"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toEndOf="@+id/search_icon"
-            app:layout_constraintTop_toTopOf="parent" />
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
-
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/search_cancel"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="9dp"
-        android:text="@string/commonui_cancel"
-        android:textColor="@color/color_FF777777"
-        android:textSize="14sp"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="@+id/search_layout"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/search_layout" />
-
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/member_list"
-        android:layout_width="0dp"
-        android:layout_height="200dp"
-        android:layout_marginTop="8dp"
-        app:layout_constraintHeight_min="372dp"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/search_layout" />
+        app:layout_constraintTop_toBottomOf="@id/tab_title" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 55 - 5
module/room/src/main/res/layout/fragment_room_online_user.xml

@@ -2,7 +2,58 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:background="@drawable/common_white_top_radius_12_bg">
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="15dp"
+        android:background="@drawable/common_white_top_radius_12_bg"
+        android:gravity="center"
+        android:text="@string/room_detail"
+        android:textColor="@color/color_222222"
+        android:textSize="15sp"
+        android:textStyle="bold"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/report_iv"
+        android:layout_width="28dp"
+        android:layout_height="28dp"
+        android:layout_marginEnd="12dp"
+        android:visibility="gone"
+        tools:visibility="visible"
+        android:src="@drawable/common_report_gray_28_ic"
+        app:layout_constraintBottom_toBottomOf="@id/title"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="@id/title" />
+
+
+
+    <include
+        android:id="@+id/layout_room_info"
+        layout="@layout/item_room_info"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="19dp"
+        android:layout_marginHorizontal="16dp"
+        app:layout_constraintTop_toBottomOf="@id/title" />
+
+    <com.adealink.weparty.module.family.view.FamilyInfoView
+        android:id="@+id/family_info_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginHorizontal="16dp"
+        android:layout_marginTop="12dp"
+        android:visibility="gone"
+        app:layout_constraintTop_toBottomOf="@+id/layout_room_info"
+        tools:layout_height="60dp"
+        tools:visibility="visible" />
 
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/member_count"
@@ -13,7 +64,7 @@
         android:paddingBottom="8dp"
         android:textColor="@color/color_AAAAAA"
         android:textSize="13sp"
-        app:layout_constraintTop_toTopOf="parent" />
+        app:layout_constraintTop_toBottomOf="@id/family_info_view" />
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/search_layout"
@@ -75,10 +126,9 @@
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/member_list"
         android:layout_width="0dp"
-        android:layout_height="0dp"
+        android:layout_height="200dp"
         android:layout_marginTop="8dp"
-        android:minHeight="372dp"
-        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintHeight_min="372dp"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/search_layout" />

+ 78 - 31
module/room/src/main/res/layout/fragment_room_summary.xml

@@ -5,35 +5,83 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <include
-        android:id="@+id/layout_room_info"
-        layout="@layout/item_room_info"
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/cl_room_info"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="19dp"
-        app:layout_constraintTop_toTopOf="parent" />
+        android:layout_marginHorizontal="20dp"
+        android:layout_marginTop="23dp"
+        android:background="@drawable/room_setting_item_content_bg"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent">
+
+        <com.adealink.frame.image.view.NetworkImageView
+            android:id="@+id/room_cover"
+            android:layout_width="72dp"
+            android:layout_height="72dp"
+            android:scaleType="centerCrop"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:placeholderImage="@drawable/common_default_avatar_ic"
+            app:roundedCornerRadius="8dp" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_room_name"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:layout_marginEnd="16dp"
+            android:gravity="start"
+            android:textColor="@color/color_game_normal"
+            android:textSize="14sp"
+            android:textStyle="bold"
+            app:layout_constraintBottom_toTopOf="@id/tv_room_id"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toEndOf="@id/room_cover"
+            app:layout_constraintTop_toTopOf="parent"
+            app:layout_constraintVertical_chainStyle="packed"
+            tools:text="Room Name" />
+
+        <androidx.appcompat.widget.AppCompatTextView
+            android:id="@+id/tv_room_id"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="4dp"
+            android:gravity="start"
+            android:textColor="@color/color_FF7AB3BD"
+            android:textSize="12sp"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="@id/tv_room_name"
+            app:layout_constraintStart_toStartOf="@id/tv_room_name"
+            app:layout_constraintTop_toBottomOf="@id/tv_room_name" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <androidx.appcompat.widget.AppCompatTextView
         android:id="@+id/member_count"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:gravity="start|center_vertical"
         android:paddingHorizontal="16dp"
         android:paddingTop="16dp"
         android:paddingBottom="8dp"
-        android:textColor="@color/color_AAAAAA"
+        android:textColor="@color/color_game_normal"
         android:textSize="13sp"
-        app:layout_constraintTop_toBottomOf="@id/layout_room_info" />
+        app:layout_constraintTop_toBottomOf="@id/cl_room_info" />
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/search_layout"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
+        android:layout_marginHorizontal="8dp"
         android:layout_marginTop="4dp"
-        android:layout_marginEnd="9dp"
-        android:background="@drawable/common_f5f7fa_radius_20_bg"
-        android:padding="12dp"
-        app:layout_constraintEnd_toStartOf="@+id/search_cancel"
+        android:background="@drawable/room_chat_input_box_bg"
+        android:paddingHorizontal="12dp"
+        android:paddingVertical="8dp"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintHeight_min="40dp"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/member_count"
         app:layout_goneMarginEnd="8dp">
@@ -49,37 +97,36 @@
 
         <androidx.appcompat.widget.AppCompatEditText
             android:id="@+id/search_edit_text"
-            style="@style/RtlTextViewStyle"
+            style="@style/EditTextStyle.Rtl"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
             android:background="@null"
             android:hint="@string/common_enter_id"
             android:imeOptions="actionSearch"
-            android:inputType="text"
+            android:inputType="number"
             android:singleLine="true"
-            android:textColor="@color/color_222222"
-            android:textColorHint="@color/color_AAAAAA"
+            android:textColor="@color/color_game_normal"
+            android:textColorHint="@color/color_game_normal"
             android:textSize="14sp"
             app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintEnd_toStartOf="@id/search_cancel"
             app:layout_constraintStart_toEndOf="@+id/search_icon"
             app:layout_constraintTop_toTopOf="parent" />
 
-    </androidx.constraintlayout.widget.ConstraintLayout>
+        <androidx.appcompat.widget.AppCompatImageView
+            android:id="@+id/search_cancel"
+            android:layout_width="16dp"
+            android:layout_height="16dp"
+            android:src="@drawable/common_clear_gray_32_ic"
+            android:visibility="gone"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            tools:visibility="visible" />
 
-    <androidx.appcompat.widget.AppCompatTextView
-        android:id="@+id/search_cancel"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginEnd="9dp"
-        android:text="@string/commonui_cancel"
-        android:textColor="@color/color_FF777777"
-        android:textSize="14sp"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="@+id/search_layout"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/search_layout" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/member_list"
@@ -87,9 +134,9 @@
         android:layout_height="0dp"
         android:layout_marginTop="8dp"
         android:minHeight="372dp"
+        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/search_layout" />
 
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 3
module/room/src/main/res/layout/layout_room_online_member.xml

@@ -2,10 +2,8 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    tools:layout_height="61.5dp"
-    tools:layout_width="67.5dp"
     tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
 
     <com.adealink.weparty.room.member.widget.RoomOnlineMemberView

+ 6 - 7
module/room/src/main/res/layout/layout_room_online_member_view.xml

@@ -2,8 +2,8 @@
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="300dp"
-    android:layout_height="match_parent"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
     android:background="@color/black"
     tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
 
@@ -21,20 +21,20 @@
 
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/rv_members"
-        android:layout_width="0dp"
+        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:layout_marginHorizontal="4dp"
         app:layout_constrainedHeight="true"
+        app:layout_constrainedWidth="true"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toStartOf="@id/cl_member_count"
         app:layout_constraintStart_toEndOf="@id/iv_fold"
-
         app:layout_constraintTop_toTopOf="parent" />
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/cl_member_count"
         android:layout_width="wrap_content"
         android:layout_height="28dp"
-        android:layout_marginStart="4dp"
         android:background="@drawable/room_online_member_count_bg"
         android:paddingHorizontal="6dp"
         app:layout_constrainedWidth="true"
@@ -42,8 +42,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toEndOf="@id/rv_members"
         app:layout_constraintTop_toTopOf="parent"
-        app:layout_constraintWidth_min="28dp"
-        app:layout_goneMarginStart="0dp">
+        app:layout_constraintWidth_min="28dp">
 
         <androidx.appcompat.widget.AppCompatImageView
             android:id="@+id/iv_member_count"

+ 1 - 0
module/room/src/main/res/values/strings.xml

@@ -402,4 +402,5 @@
     <string name="room_game_admin_invite_tip">The room admin invites you to play %s</string>
     <string name="room_mic_seat_kicked_by_room_game_restart">The game is restarted, please rejoin the game</string>
     <string name="room_multi_people">%s people</string>
+    <string name="room_create_upload_cover_tips">Upload Room Cover</string>
 </resources>