honghengqiang 2 years ago
parent
commit
33795076f7
52 changed files with 1372 additions and 247 deletions
  1. 18 0
      baseswago/src/main/java/com/swago/baseswago/agora/AgoraManager.kt
  2. 2 0
      baseswago/src/main/java/com/swago/baseswago/agora/ISwagoIRtcEngineEventHandler.kt
  3. 6 3
      baseswago/src/main/java/com/swago/baseswago/baseroom/ui/AbsAnchorActivity.kt
  4. 5 2
      baseswago/src/main/java/com/swago/baseswago/baseroom/ui/AbsUserActivity.kt
  5. 101 35
      baseswago/src/main/java/com/swago/baseswago/inter/RoomApi.kt
  6. 151 0
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/PKInfoModel.java
  7. 57 0
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/PKLiverModel.kt
  8. 8 8
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/ProcessPKModel.kt
  9. 10 4
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/PunishPKModel.kt
  10. 41 3
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/SendPKModel.kt
  11. 11 10
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/StartPKModel.kt
  12. 1 1
      baseswago/src/main/java/com/swago/baseswago/model/live/pk/StopPKModel.kt
  13. 2 0
      baseswago/src/main/res/values-in/strings.xml
  14. 2 0
      baseswago/src/main/res/values-ms/strings.xml
  15. 2 0
      baseswago/src/main/res/values-zh/strings.xml
  16. 5 0
      baseswago/src/main/res/values/strings.xml
  17. BIN
      room/src/main/assets/cry.svga
  18. BIN
      room/src/main/assets/laugh.svga
  19. BIN
      room/src/main/assets/pk_fail.svga
  20. BIN
      room/src/main/assets/pk_win.svga
  21. 61 36
      room/src/main/java/com/swago/room/anchor/AnchorRoomActivity.kt
  22. 51 0
      room/src/main/java/com/swago/room/anchor/AnchorRoomFragment.kt
  23. 13 1
      room/src/main/java/com/swago/room/base/BaseComFragment.kt
  24. 2 1
      room/src/main/java/com/swago/room/gift/GiftVm.kt
  25. 1 1
      room/src/main/java/com/swago/room/pk/IPKListener.kt
  26. 55 2
      room/src/main/java/com/swago/room/pk/PKAcceptDialog.kt
  27. 12 0
      room/src/main/java/com/swago/room/pk/PKAudienceAdapter.kt
  28. 81 3
      room/src/main/java/com/swago/room/pk/PKInviteDialog.kt
  29. 189 49
      room/src/main/java/com/swago/room/pk/PKLayoutView.kt
  30. 28 2
      room/src/main/java/com/swago/room/pk/PKListAdapter.kt
  31. 54 16
      room/src/main/java/com/swago/room/pk/PKSearchLisDialog.kt
  32. 8 0
      room/src/main/java/com/swago/room/pk/PKStateManager.kt
  33. 207 25
      room/src/main/java/com/swago/room/pk/PkVm.kt
  34. 102 13
      room/src/main/java/com/swago/room/user/UserRoomActivity.kt
  35. 18 0
      room/src/main/java/com/swago/room/user/UserRoomFragment.kt
  36. 7 0
      room/src/main/java/com/swago/room/widget/AnchorFooterView.kt
  37. 1 0
      room/src/main/res/layout/activity_anchor_room.xml
  38. 2 0
      room/src/main/res/layout/dialog_pk_accept.xml
  39. 12 9
      room/src/main/res/layout/dialog_pk_invite.xml
  40. 1 1
      room/src/main/res/layout/dialog_pk_search.xml
  41. 0 3
      room/src/main/res/layout/fragment_base_com.xml
  42. 2 1
      room/src/main/res/layout/item_pk_search.xml
  43. 7 0
      room/src/main/res/layout/item_pk_seat.xml
  44. 12 1
      room/src/main/res/layout/layout_anchor_footer_view.xml
  45. 14 14
      room/src/main/res/layout/layout_pk_view.xml
  46. 8 0
      room/src/main/res/layout/layout_user_room.xml
  47. BIN
      room/src/main/res/mipmap-xxhdpi/bg_room.webp
  48. BIN
      room/src/main/res/mipmap-xxhdpi/first.png
  49. BIN
      room/src/main/res/mipmap-xxhdpi/live_pk.webp
  50. BIN
      room/src/main/res/mipmap-xxhdpi/second.png
  51. BIN
      room/src/main/res/mipmap-xxhdpi/third.png
  52. 2 3
      user/src/main/java/com/swago/user/adapter/BlackListAdapter.kt

+ 18 - 0
baseswago/src/main/java/com/swago/baseswago/agora/AgoraManager.kt

@@ -76,6 +76,22 @@ object AgoraManager {
                         iSwagoIRtcEngineEventHandler?.onConnectionStateChanged(state, reason)
                     }
 
+                    override fun onChannelMediaRelayStateChanged(state: Int, code: Int) {
+                        super.onChannelMediaRelayStateChanged(state, code)
+                        Log.d("StateChanged","结果--$state----$code")
+                        iSwagoIRtcEngineEventHandler?.onChannelMediaRelayStateChanged(state, code)
+                    }
+
+                    override fun onChannelMediaRelayEvent(code: Int) {
+                        super.onChannelMediaRelayEvent(code)
+                        Log.d("ChannelMediaRelayEvent","结果--$code")
+                    }
+
+                    override fun onUserJoined(uid: Int, elapsed: Int) {
+                        super.onUserJoined(uid, elapsed)
+                        Log.d("onUserJoined","结果--$uid")
+                    }
+
                 })
             setChannelProfile()
         } catch (e: Exception) {
@@ -122,6 +138,7 @@ object AgoraManager {
      * 观众拉取远端主播画面
      */
     fun setupRemoteVideo(context: Context, anchorId: Int, mLocalContainer: FrameLayout) {
+        mLocalContainer.removeAllViews()
         val remoteView = RtcEngine.CreateRendererView(context)
         mLocalContainer.addView(remoteView)
         val result = mRtcEngine?.setupRemoteVideo(
@@ -205,6 +222,7 @@ object AgoraManager {
         val destChannelInfo = ChannelMediaInfo(destChannelName, destChannelToken,uid)
         mediaRelayConfiguration.setDestChannelInfo(destChannelName,destChannelInfo)
         val result = mRtcEngine?.startChannelMediaRelay(mediaRelayConfiguration)
+        Log.d("PK跨频道","结果---$result")
     }
 
     /**

+ 2 - 0
baseswago/src/main/java/com/swago/baseswago/agora/ISwagoIRtcEngineEventHandler.kt

@@ -15,4 +15,6 @@ interface ISwagoIRtcEngineEventHandler {
 
     fun onConnectionStateChanged(state: Int, reason: Int)
 
+    fun onChannelMediaRelayStateChanged(state: Int, code: Int)
+
 }

+ 6 - 3
baseswago/src/main/java/com/swago/baseswago/baseroom/ui/AbsAnchorActivity.kt

@@ -1,6 +1,7 @@
 package com.swago.baseswago.baseroom.ui
 
 import androidx.viewbinding.ViewBinding
+import com.swago.baseswago.activity.BaseActivity
 import com.swago.baseswago.activity.BaseXActivity
 import com.swago.baseswago.baseroom.IRoomActiveListener
 import com.swago.baseswago.baseroom.IRoomInfo
@@ -11,16 +12,18 @@ import com.swago.baseswago.baseroom.SwagoRoomManager
  *@date 2021/10/4 10:43
  *description:
  */
-abstract class AbsAnchorActivity <VB: ViewBinding,T: IRoomInfo> : BaseXActivity<VB>(),IRoomActiveListener{
+abstract class AbsAnchorActivity <VB: ViewBinding,T: IRoomInfo> : BaseActivity<VB>(),IRoomActiveListener{
 
     var roleType = RoleType.anchor
 
-    override fun initOther() {
+    override fun initView() {
         SwagoRoomManager.addListener(this)
         SwagoRoomManager.roleType = roleType
-
+        initLiveData()
     }
 
+    abstract fun initLiveData()
+
     override fun onDestroy() {
         super.onDestroy()
         if (SwagoRoomManager.iRoomInfo != null){

+ 5 - 2
baseswago/src/main/java/com/swago/baseswago/baseroom/ui/AbsUserActivity.kt

@@ -3,6 +3,7 @@ package com.swago.baseswago.baseroom.ui
 import android.view.View
 import android.view.ViewGroup
 import androidx.recyclerview.widget.OrientationHelper
+import com.swago.baseswago.activity.BaseActivity
 import com.swago.baseswago.activity.BaseXActivity
 import com.swago.baseswago.baseroom.IRoomActiveListener
 import com.swago.baseswago.baseroom.IRoomInfo
@@ -17,7 +18,7 @@ import java.util.concurrent.CopyOnWriteArrayList
  *@date 2021/10/10 10:15
  *description:
  */
-abstract class AbsUserActivity<T: ActivityAbsRoomUserBinding,E: IRoomInfo> : BaseXActivity<ActivityAbsRoomUserBinding>(), IRoomActiveListener {
+abstract class AbsUserActivity<T: ActivityAbsRoomUserBinding,E: IRoomInfo> : BaseActivity<ActivityAbsRoomUserBinding>(), IRoomActiveListener {
 
     var roleType = RoleType.user
 
@@ -31,7 +32,7 @@ abstract class AbsUserActivity<T: ActivityAbsRoomUserBinding,E: IRoomInfo> : Bas
         PagerLayoutManager(this,OrientationHelper.VERTICAL)
     }
 
-    override fun initOther() {
+    override fun initView() {
         pagerLayoutManager.setViewGroup(roomCoverView,object:PagerLayoutManager.IreloadInterface{
             override fun onReloadPage(position: Int, isBottom: Boolean, view: View?) {
                 var p = position
@@ -56,6 +57,7 @@ abstract class AbsUserActivity<T: ActivityAbsRoomUserBinding,E: IRoomInfo> : Bas
         pagerLayoutManager.scrollToPositionWithOffset(mCurrentPosition,0)
 
         initUserRoomView()
+        initLiveData()
     }
 
     fun scrollToPosition(index:Int){
@@ -76,5 +78,6 @@ abstract class AbsUserActivity<T: ActivityAbsRoomUserBinding,E: IRoomInfo> : Bas
     }
 
     abstract fun initUserRoomView()
+    abstract fun initLiveData()
 
 }

+ 101 - 35
baseswago/src/main/java/com/swago/baseswago/inter/RoomApi.kt

@@ -6,6 +6,8 @@ import com.swago.baseswago.model.live.*
 import com.swago.baseswago.model.live.game.GameListModel
 import com.swago.baseswago.model.live.gift.GiftAllModel
 import com.swago.baseswago.model.live.gift.GiftSendModel
+import com.swago.baseswago.model.live.pk.ListPKLiverModel
+import com.swago.baseswago.model.live.pk.PKInfoModel
 import retrofit2.http.*
 
 /**
@@ -25,14 +27,14 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/start/broadcast")
-    suspend fun startLive(@Field("game_type")game_type:Int):RoomModel
+    suspend fun startLive(@Field("game_type") game_type: Int): RoomModel
 
 
     /**
      * 关播
      */
     @POST("/v1/rtc/end/broadcast")
-    suspend fun closeLive():AnchorClosedModel
+    suspend fun closeLive(): AnchorClosedModel
 
 
     /**
@@ -40,14 +42,14 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/join/broadcast")
-    suspend fun joinRoom(@Field("room_id")room_id:String):RoomModel
+    suspend fun joinRoom(@Field("room_id") room_id: String): RoomModel
 
     /**
      * 退出房间
      */
     @FormUrlEncoded
     @POST("/v1/rtc/leave/broadcast")
-    suspend fun leaveRoom(@Field("room_id")room_id:String):Any
+    suspend fun leaveRoom(@Field("room_id") room_id: String): Any
 
 
     /**
@@ -55,7 +57,11 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/user/list")
-    suspend fun getRoomUser(@Field("room_id")room_id:String,@Field("page")page:Int=1,@Field("page_size")page_size:Int=5):RoomUserModel
+    suspend fun getRoomUser(
+        @Field("room_id") room_id: String,
+        @Field("page") page: Int = 1,
+        @Field("page_size") page_size: Int = 5
+    ): RoomUserModel
 
     /**
      * 直播间排行榜
@@ -63,34 +69,44 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/fans/rank/list")
-    suspend fun getRankList(@Field("room_id")room_id:String,@Field("rank_type")rank_type:Int,@Field("page")page:Int=1,@Field("page_size")page_size:Int=20):RankListModel
+    suspend fun getRankList(
+        @Field("room_id") room_id: String,
+        @Field("rank_type") rank_type: Int,
+        @Field("page") page: Int = 1,
+        @Field("page_size") page_size: Int = 20
+    ): RankListModel
 
 
     /**
      * 直播间礼物
      */
     @POST("/v1/rtc/gift/list")
-    suspend fun getGiftList():List<GiftAllModel>
+    suspend fun getGiftList(): List<GiftAllModel>
 
     /**
      * 赠送礼物
      */
     @FormUrlEncoded
     @POST("/v1/rtc/buy/gift")
-    suspend fun sendGift(@Field("room_id")room_id:String,
-                         @Field("gift_id")gift_id:String,
-                         @Field("gift_batch")gift_batch:Int,
-                         @Field("gift_receive_id")gift_receive_id:String,
-                         @Field("is_combo")is_combo:Int,
-                         @Field("gift_num")gift_num:Int): GiftSendModel
+    suspend fun sendGift(
+        @Field("room_id") room_id: String,
+        @Field("gift_id") gift_id: String,
+        @Field("gift_batch") gift_batch: Int,
+        @Field("gift_receive_id") gift_receive_id: String,
+        @Field("is_combo") is_combo: Int,
+        @Field("gift_num") gift_num: Int,
+        @Field("pk_id") pk_id: String,
+    ): GiftSendModel
 
     /**
      * 用户在直播间权限
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/auth")
-    suspend fun getUserRoomAuth(@Field("room_id")room_id:String,
-                                @Field("user_id")user_id:String):RoomAuthModel
+    suspend fun getUserRoomAuth(
+        @Field("room_id") room_id: String,
+        @Field("user_id") user_id: String
+    ): RoomAuthModel
 
     /**
      * 剔除直播间
@@ -98,18 +114,22 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/remove/user")
-    suspend fun kickUserFromRoom(@Field("room_id")room_id:String,
-                                 @Field("user_id")user_id:String,
-                                 @Field("type")type:Int)
+    suspend fun kickUserFromRoom(
+        @Field("room_id") room_id: String,
+        @Field("user_id") user_id: String,
+        @Field("type") type: Int
+    )
 
     /**
      * 用户禁言
      */
     @FormUrlEncoded
     @POST("/v1/rtc/forbid/user/msg")
-    suspend fun muteUerFromRoom(@Field("room_id")room_id:String,
-                                @Field("user_id")user_id:String,
-                                @Field("type")type:Int)
+    suspend fun muteUerFromRoom(
+        @Field("room_id") room_id: String,
+        @Field("user_id") user_id: String,
+        @Field("type") type: Int
+    )
 
     /**
      * 直播间拉黑
@@ -118,29 +138,31 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/black/user")
-    suspend fun blackUser(@Field("black_user_id")black_user_id:String,
-                          @Field("black_type")black_type:Int,
-                          @Field("type")type:Int)
+    suspend fun blackUser(
+        @Field("black_user_id") black_user_id: String,
+        @Field("black_type") black_type: Int,
+        @Field("type") type: Int
+    )
 
 
     /**
      * 获取分享配置
      */
     @POST("/v1/rtc/broadcast/share/link")
-    suspend fun getShareConfig():ShareConfig
+    suspend fun getShareConfig(): ShareConfig
 
     /**
      * 获取直播间配置
      */
     @POST("/v1/rtc/broadcast/setting")
-    suspend fun getRoomConfig():RoomConfig
+    suspend fun getRoomConfig(): RoomConfig
 
     /**
      * 获取红包列表
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/package/list")
-    suspend fun getRedEnvelopeList(@Field("room_id")room_id:String):ArrayList<RedEnvelope>
+    suspend fun getRedEnvelopeList(@Field("room_id") room_id: String): ArrayList<RedEnvelope>
 
 
     /**
@@ -148,9 +170,11 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/send/package")
-    suspend fun sendRedEnvelope(@Field("room_id")room_id:String,
-                                @Field("package_total_coins")package_total_coins:String,
-                                @Field("package_total_num")package_total_num:Int,):Any
+    suspend fun sendRedEnvelope(
+        @Field("room_id") room_id: String,
+        @Field("package_total_coins") package_total_coins: String,
+        @Field("package_total_num") package_total_num: Int,
+    ): Any
 
 
     /**
@@ -158,8 +182,10 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/receive/package")
-    suspend fun getRedEnvelopeCoin(@Field("room_id")room_id:String,
-                                   @Field("package_id")package_id:String):RedEnvelopeResult
+    suspend fun getRedEnvelopeCoin(
+        @Field("room_id") room_id: String,
+        @Field("package_id") package_id: String
+    ): RedEnvelopeResult
 
 
     /**
@@ -167,16 +193,56 @@ interface RoomApi {
      */
     @FormUrlEncoded
     @POST("/v1/rtc/broadcast/user/detail")
-    suspend fun getMomentModel(@Field("room_id")room_id:String):MomentModel
+    suspend fun getMomentModel(@Field("room_id") room_id: String): MomentModel
 
 
     /***********************PK*********************************/
 
-//    @POST("/v1/rtc/broadcast/pk/list")
-//    suspend fun getPKLiverList():List<>
+    /**
+     * 获取主播PK列表
+     */
+    @FormUrlEncoded
+    @POST("/v1/rtc/broadcast/pk/list")
+    suspend fun getPKLiverList(@Field("search_keyword") search_keyword: String): ListPKLiverModel
+
+    /**
+     * 用户发起PK接口
+     */
+    @FormUrlEncoded
+    @POST("/v1/rtc/broadcast/pk")
+    suspend fun invitePK(@Field("pk_user_id") pk_user_id: String): Any
+
+    /**
+     * 被邀请的对象接受或者主动拒绝
+     *  //类型(1接受2拒绝)
+     */
+    @FormUrlEncoded
+    @POST("/v1/rtc/broadcast/pk/accept")
+    suspend fun acceptRefusePK(
+        @Field("type") type: Int,
+        @Field("user_id") user_id: String
+    ): Any
 
+    /**
+     * 发起PK方主动取消邀请
+     */
+    @POST("/v1/rtc/broadcast/pk/cancel")
+    suspend fun cancelInvitePK(): Any
+
+    /**
+     * PK确认接口
+     */
+    @FormUrlEncoded
+    @POST("/v1/rtc/broadcast/pk/act")
+    suspend fun pkSure(@Field("pk_id") pk_id: String): Any
 
 
+    /**
+     * 获取直播间信息
+     */
+    @FormUrlEncoded
+    @POST("/v1/rtc/broadcast/pk/detail")
+    suspend fun getPKInfo(@Field("room_id") room_id: String): PKInfoModel
 
     /***********************PK*********************************/
 

+ 151 - 0
baseswago/src/main/java/com/swago/baseswago/model/live/pk/PKInfoModel.java

@@ -0,0 +1,151 @@
+package com.swago.baseswago.model.live.pk;
+
+import java.util.List;
+
+public class PKInfoModel {
+
+    private int progressValue;
+    private int oppositeProgressValue;
+    private int roomState;
+    private int pkEndTime;
+    private int pkResultTime;
+    private String roomId;
+    private String userId;
+    private String oppositeRoomId;
+    private String oppositeUserId;
+    private String oppositeUserName;
+    private String oppositeAvatar;
+    private String pkId;
+    private int roomResult;
+    private int oppositeRoomResult;
+    private List<PKSeat> roomAudienceList;
+    private List<PKSeat> oppositeRoomAudienceList;
+
+    public int getProgressValue() {
+        return progressValue;
+    }
+
+    public void setProgressValue(int progressValue) {
+        this.progressValue = progressValue;
+    }
+
+    public int getOppositeProgressValue() {
+        return oppositeProgressValue;
+    }
+
+    public void setOppositeProgressValue(int oppositeProgressValue) {
+        this.oppositeProgressValue = oppositeProgressValue;
+    }
+
+    public int getRoomState() {
+        return roomState;
+    }
+
+    public void setRoomState(int roomState) {
+        this.roomState = roomState;
+    }
+
+    public int getPkEndTime() {
+        return pkEndTime;
+    }
+
+    public void setPkEndTime(int pkEndTime) {
+        this.pkEndTime = pkEndTime;
+    }
+
+    public int getPkResultTime() {
+        return pkResultTime;
+    }
+
+    public void setPkResultTime(int pkResultTime) {
+        this.pkResultTime = pkResultTime;
+    }
+
+    public String getRoomId() {
+        return roomId;
+    }
+
+    public void setRoomId(String roomId) {
+        this.roomId = roomId;
+    }
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public String getOppositeRoomId() {
+        return oppositeRoomId;
+    }
+
+    public void setOppositeRoomId(String oppositeRoomId) {
+        this.oppositeRoomId = oppositeRoomId;
+    }
+
+    public String getOppositeUserId() {
+        return oppositeUserId;
+    }
+
+    public void setOppositeUserId(String oppositeUserId) {
+        this.oppositeUserId = oppositeUserId;
+    }
+
+    public String getOppositeUserName() {
+        return oppositeUserName;
+    }
+
+    public void setOppositeUserName(String oppositeUserName) {
+        this.oppositeUserName = oppositeUserName;
+    }
+
+    public String getOppositeAvatar() {
+        return oppositeAvatar;
+    }
+
+    public void setOppositeAvatar(String oppositeAvatar) {
+        this.oppositeAvatar = oppositeAvatar;
+    }
+
+    public String getPkId() {
+        return pkId;
+    }
+
+    public void setPkId(String pkId) {
+        this.pkId = pkId;
+    }
+
+    public int getRoomResult() {
+        return roomResult;
+    }
+
+    public void setRoomResult(int roomResult) {
+        this.roomResult = roomResult;
+    }
+
+    public int getOppositeRoomResult() {
+        return oppositeRoomResult;
+    }
+
+    public void setOppositeRoomResult(int oppositeRoomResult) {
+        this.oppositeRoomResult = oppositeRoomResult;
+    }
+
+    public List<PKSeat> getRoomAudienceList() {
+        return roomAudienceList;
+    }
+
+    public void setRoomAudienceList(List<PKSeat> roomAudienceList) {
+        this.roomAudienceList = roomAudienceList;
+    }
+
+    public List<PKSeat> getOppositeRoomAudienceList() {
+        return oppositeRoomAudienceList;
+    }
+
+    public void setOppositeRoomAudienceList(List<PKSeat> oppositeRoomAudienceList) {
+        this.oppositeRoomAudienceList = oppositeRoomAudienceList;
+    }
+}

+ 57 - 0
baseswago/src/main/java/com/swago/baseswago/model/live/pk/PKLiverModel.kt

@@ -0,0 +1,57 @@
+package com.swago.baseswago.model.live.pk
+
+import android.os.Parcel
+import android.os.Parcelable
+
+data class PKLiverModel(
+
+//    "id": 20000014, //用户ID
+//    "user_name": "sw20000014", //用户昵称
+//"user_sex": 0, //用户性别(0男1女)
+//"user_head_img_url": "https://swago-1304432552.cos.ap-hongkong.myqcloud.com/head.png", //用户头像
+//"user_fans_num": 0, //粉丝数量
+//"user_level": 1 //主播等级
+        var id :String ="0",
+        var user_name:String = "",
+        var user_sex:Int,
+        var user_head_img_url:String = "",
+        var user_fans_num:String="",
+        var user_level:Int
+):Parcelable {
+        constructor(parcel: Parcel) : this(
+                parcel.readString().toString(),
+                parcel.readString().toString(),
+                parcel.readInt(),
+                parcel.readString().toString(),
+                parcel.readString().toString(),
+                parcel.readInt()
+        ) {
+        }
+
+        override fun writeToParcel(parcel: Parcel, flags: Int) {
+                parcel.writeString(id)
+                parcel.writeString(user_name)
+                parcel.writeInt(user_sex)
+                parcel.writeString(user_head_img_url)
+                parcel.writeString(user_fans_num)
+                parcel.writeInt(user_level)
+        }
+
+        override fun describeContents(): Int {
+                return 0
+        }
+
+        companion object CREATOR : Parcelable.Creator<PKLiverModel> {
+                override fun createFromParcel(parcel: Parcel): PKLiverModel {
+                        return PKLiverModel(parcel)
+                }
+
+                override fun newArray(size: Int): Array<PKLiverModel?> {
+                        return arrayOfNulls(size)
+                }
+        }
+}
+
+data class ListPKLiverModel(
+        val list:List<PKLiverModel>?
+)

+ 8 - 8
baseswago/src/main/java/com/swago/baseswago/model/live/pk/ProcessPKModel.kt

@@ -1,15 +1,15 @@
 package com.swago.baseswago.model.live.pk
 
 data class ProcessPKModel(
-    val roomId:String="",
-    val progressValue:Int=0,
-    val roomAudienceList:List<PKSeat>,
-    val oppositeRoomId:String="",
-    val oppositeProgressValue:Int=0,
-    val oppositeRoomAudienceList:List<PKSeat>,
+    var roomId:String="",
+    var progressValue:Int=0,
+    var roomAudienceList:List<PKSeat> = ArrayList(),
+    var oppositeRoomId:String="",
+    var oppositeProgressValue:Int=0,
+    var oppositeRoomAudienceList:List<PKSeat> = ArrayList(),
 )
 
 data class PKSeat(
-    val userId:String = "",
-    val userAvatar:String=""
+    var userId:String = "",
+    var userAvatar:String=""
 )

+ 10 - 4
baseswago/src/main/java/com/swago/baseswago/model/live/pk/PunishPKModel.kt

@@ -4,8 +4,14 @@ package com.swago.baseswago.model.live.pk
  * 结算结果
  */
 data class PunishPKModel(
-    val roomId:String="",
-    val roomResult:Int=0,
-    val oppositeRoomId:String="",
-    val oppositeRoomResult:Int=0,
+    var userId:String="0",
+    var roomId:String="",
+    var roomResult:Int=0,
+    var oppositeUserId:String ="0",
+    var oppositeRoomId:String="",
+    var oppositeRoomResult:Int=0,
+    var oppositeName:String = "",
+    var oppositeAvatar:String = "",
+
+    var pkId:String="0"
 )

+ 41 - 3
baseswago/src/main/java/com/swago/baseswago/model/live/pk/SendPKModel.kt

@@ -1,15 +1,53 @@
 package com.swago.baseswago.model.live.pk
 
+import android.os.Parcel
+import android.os.Parcelable
+
 /**
  * 发起PK
  * actionType  1(发起PK) 2(发送方取消PK) 3(拒绝PK) 4(接受PK) 5(自动拒绝PK)
  */
 data class SendPKModel (
-    val senderId:String = "",
+    val senderId:String = "0",
     val senderName:String = "",
     val senderAvatar:String = "",
-    val receiverId:String = "",
+    val receiverId:String = "0",
     val receiverName:String = "",
     val receiverAvatar:String = "",
     val actionType:Int = 0
-)
+):Parcelable {
+    constructor(parcel: Parcel) : this(
+        parcel.readString().toString(),
+        parcel.readString().toString(),
+        parcel.readString().toString(),
+        parcel.readString().toString(),
+        parcel.readString().toString(),
+        parcel.readString().toString(),
+        parcel.readInt()
+    ) {
+    }
+
+    override fun writeToParcel(parcel: Parcel, flags: Int) {
+        parcel.writeString(senderId)
+        parcel.writeString(senderName)
+        parcel.writeString(senderAvatar)
+        parcel.writeString(receiverId)
+        parcel.writeString(receiverName)
+        parcel.writeString(receiverAvatar)
+        parcel.writeInt(actionType)
+    }
+
+    override fun describeContents(): Int {
+        return 0
+    }
+
+    companion object CREATOR : Parcelable.Creator<SendPKModel> {
+        override fun createFromParcel(parcel: Parcel): SendPKModel {
+            return SendPKModel(parcel)
+        }
+
+        override fun newArray(size: Int): Array<SendPKModel?> {
+            return arrayOfNulls(size)
+        }
+    }
+}

+ 11 - 10
baseswago/src/main/java/com/swago/baseswago/model/live/pk/StartPKModel.kt

@@ -4,14 +4,15 @@ package com.swago.baseswago.model.live.pk
  * PK开始
  */
 data class StartPKModel(
-    val roomId:String="",
-    val userId:String = "",
-    val oppositeRoomId:String = "",
-    val oppositeUserId:String = "",
-    val oppositeName:String = "",
-    val oppositeAvatar:String = "",
-    val pkResultTime:Int = 0,
-    val pkEndTime:Int = 0,
-    val sourceToken:String = "",
-    val destToken:String = "",
+    var roomId:String="",
+    var userId:String = "0",
+    var oppositeRoomId:String = "",
+    var oppositeUserId:String = "0",
+    var oppositeName:String = "",
+    var oppositeAvatar:String = "",
+    var pkResultTime:Int = 0,
+    var pkEndTime:Int = 0,
+    var sourceToken:String = "",
+    var destToken:String = "",
+    var pkId:String = "0",
 )

+ 1 - 1
baseswago/src/main/java/com/swago/baseswago/model/live/pk/StopPKModel.kt

@@ -4,5 +4,5 @@ package com.swago.baseswago.model.live.pk
  * PK结束
  */
 data class StopPKModel(
-    val roomId:String=""
+    var roomId:String=""
 )

+ 2 - 0
baseswago/src/main/res/values-in/strings.xml

@@ -183,5 +183,7 @@
     <string name="invites_you_to_pk">%s invites you to PK</string>
     <string name="accept_swago">Accept</string>
     <string name="refuse_swago">Refuse</string>
+    <string name="peer_liver_refuse_pk">对方拒绝您的PK</string>
+    <string name="send_pk_liver_cancel">发起方取消了PK</string>
 
 </resources>

+ 2 - 0
baseswago/src/main/res/values-ms/strings.xml

@@ -181,4 +181,6 @@
     <string name="invites_you_to_pk">%s invites you to PK</string>
     <string name="accept_swago">Accept</string>
     <string name="refuse_swago">Refuse</string>
+    <string name="peer_liver_refuse_pk">对方拒绝您的PK</string>
+    <string name="send_pk_liver_cancel">发起方取消了PK</string>
 </resources>

+ 2 - 0
baseswago/src/main/res/values-zh/strings.xml

@@ -181,5 +181,7 @@
     <string name="invites_you_to_pk">%s invites you to PK</string>
     <string name="accept_swago">Accept</string>
     <string name="refuse_swago">Refuse</string>
+    <string name="peer_liver_refuse_pk">对方拒绝您的PK</string>
+    <string name="send_pk_liver_cancel">发起方取消了PK</string>
 
 </resources>

+ 5 - 0
baseswago/src/main/res/values/strings.xml

@@ -189,6 +189,8 @@
     <string name="got_it">Got it</string>
     <string name="force_closed_by_admin">Your broadcast room has been closed by an administrator</string>
     <string name="game_prize">%s just won %s coins in %s, that\'s awesome!</string>
+
+
     <string name="select_pk_anchor">Select PK Anchor</string>
     <string name="please_enter_the_host_id_name">Please enter the host ID / name</string>
     <string name="invite_pk">Invite PK</string>
@@ -198,5 +200,8 @@
     <string name="invites_you_to_pk">%s invites you to PK</string>
     <string name="accept_swago">Accept</string>
     <string name="refuse_swago">Refuse</string>
+    <string name="fans_x">Fans:%s</string>
+    <string name="peer_liver_refuse_pk">对方拒绝您的PK</string>
+    <string name="send_pk_liver_cancel">发起方取消了PK</string>
 
 </resources>

BIN
room/src/main/assets/cry.svga


BIN
room/src/main/assets/laugh.svga


BIN
room/src/main/assets/pk_fail.svga


BIN
room/src/main/assets/pk_win.svga


+ 61 - 36
room/src/main/java/com/swago/room/anchor/AnchorRoomActivity.kt

@@ -37,6 +37,7 @@ import com.swago.room.dialog.CanStartLiveDialog
 import com.swago.room.dialog.ForceCloseRoomDialog
 import com.swago.room.pk.IPKListener
 import com.swago.room.pk.PKStateManager
+import com.swago.room.pk.PkVm
 import com.swago.room.service.AgoraForegroundService
 import com.swago.room.service.AgoraForegroundService.ACTION_START_FOREGROUND_SERVICE
 import com.swago.room.service.AgoraForegroundService.ACTION_STOP_FOREGROUND_SERVICE
@@ -45,6 +46,9 @@ import com.swago.room.vm.RoomOtherVm
 import com.swago.room.vm.RoomVm
 import com.tencent.qcloud.tim.uikit.TUIKitImpl
 import com.tencent.qcloud.tim.uikit.base.IMEventListener
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
 import java.util.*
 
 /**
@@ -52,36 +56,37 @@ import java.util.*
  *description:
  */
 @Route(path = ARouteConstant.Room.anchor)
-class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo>(),
+class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding, IRoomInfo>(),
     ISwagoIRtcEngineEventHandler, IPKListener {
 
     private val roomVm by viewModels<RoomVm>()
     private val roomOtherVm by viewModels<RoomOtherVm>()
     private val msgVm by viewModels<MsgVm>()
+    private val pkVm by viewModels<PkVm>()
 
 
-    private var agoraService : Intent? = null
+    private var agoraService: Intent? = null
 
-    private val fragments = arrayListOf(NoContentFragment(),AnchorRoomFragment())
+    private val fragments = arrayListOf(NoContentFragment(), AnchorRoomFragment())
 
-    private val adapter = SwagoAdapter(fragments,supportFragmentManager)
+    private val adapter = SwagoAdapter(fragments, supportFragmentManager)
 
-    override fun loadData() {}
-
-    private var anchorRoomFragment:AnchorRoomFragment? = null
+    private var anchorRoomFragment: AnchorRoomFragment? = null
 
     override fun initLiveData() {
+        PKStateManager.resetData()
         roomVm.init()
         msgVm.init()
+        pkVm.init()
         roomOtherVm.getGameList()
         PKStateManager.addPKListener(this)
         initPeerAnchorLayoutParams()
         window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
-        agoraService = Intent(this,AgoraForegroundService::class.java)
-        AgoraManager.initializeEngine(this,this)
+        agoraService = Intent(this, AgoraForegroundService::class.java)
+        AgoraManager.initializeEngine(this, this)
         AgoraManager.setVideoConfiguration()
         AgoraManager.setClientRole(RoleType.anchor)
-        AgoraManager.setupLocalVideo(this,binding.flLocal)
+        AgoraManager.setupLocalVideo(this, binding.flLocal)
         anchorRoomFragment = fragments[1] as AnchorRoomFragment
         binding.viewPager.adapter = adapter
 
@@ -102,7 +107,7 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
         })
         binding.tvStartLive.setOnClickListener(object : NoDoubleClickListener() {
             override fun onClick() {
-                if (roomVm.currentGameType != -1){
+                if (roomVm.currentGameType != -1) {
                     binding.tvStartLive.isEnabled = false
                     val userModel = UserRoomModel()
                     SwagoRoomManager.changeRoom(userModel)
@@ -120,32 +125,34 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
         }
 
         msgVm.forceCloseAnchorRoom = {
-            ForceCloseRoomDialog.newInstance(it).show(supportFragmentManager,"ForceCloseRoomDialog")
+            ForceCloseRoomDialog.newInstance(it)
+                .show(supportFragmentManager, "ForceCloseRoomDialog")
         }
 
         roomVm.showBannerTime = {
-            CanStartLiveDialog.newInstance(it).show(supportFragmentManager,"CanStartLiveDialog")
+            CanStartLiveDialog.newInstance(it).show(supportFragmentManager, "CanStartLiveDialog")
         }
 
-        roomVm.anchorCloseLiveData.observe(this){
+        roomVm.anchorCloseLiveData.observe(this) {
             val dialog = AnchorCloseDialog.newInstance(it)
-            dialog.show(supportFragmentManager,"AnchorCloseDialog")
+            dialog.show(supportFragmentManager, "AnchorCloseDialog")
         }
 
-        roomOtherVm.gameListModelLiveData.observe(this){
-            anchorRoomFragment?.setFooterGameIcon(it.status==1)
-            if (it.status == 1){
+        roomOtherVm.gameListModelLiveData.observe(this) {
+            anchorRoomFragment?.setFooterGameIcon(it.status == 1)
+            if (it.status == 1) {
                 binding.rvGame.visibility = View.VISIBLE
-            }else {
+            } else {
                 binding.rvGame.visibility = View.GONE
             }
 
             it.list?.let { data ->
-                if (data.isNotEmpty()){
+                if (data.isNotEmpty()) {
                     roomVm.currentGameType = data[0].game_type
 
                     data[0].selected = true
-                    binding.rvGame.layoutManager = LinearLayoutManager(this,RecyclerView.HORIZONTAL,false)
+                    binding.rvGame.layoutManager =
+                        LinearLayoutManager(this, RecyclerView.HORIZONTAL, false)
                     val adapter = GameAdapter()
                     binding.rvGame.adapter = adapter
                     adapter.setNewData(data)
@@ -162,7 +169,11 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
 
     override fun joinedRoom(iRoomInfo: IRoomInfo) {
         UserInfo.getUserInfo()?.let {
-            AgoraManager.joinChannel(iRoomInfo.getChannelName(),it.id.toInt(),iRoomInfo.getAgoraToken())
+            AgoraManager.joinChannel(
+                iRoomInfo.getChannelName(),
+                it.id.toInt(),
+                iRoomInfo.getAgoraToken()
+            )
         }
         binding.clPrepare.visibility = View.GONE
         binding.viewPager.currentItem = 1
@@ -173,13 +184,14 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
     }
 
     override fun closeRoomed() {
+        PKStateManager.resetData()
         AgoraManager.closedRoom()
     }
 
     override fun onBackPressed() {
-        if (binding.clPrepare.visibility == View.VISIBLE){
+        if (binding.clPrepare.visibility == View.VISIBLE) {
             anchorCloseRoom()
-        }else{
+        } else {
             SwagoRoomManager.closeRoom()
         }
     }
@@ -221,6 +233,12 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
 
     }
 
+    override fun onChannelMediaRelayStateChanged(state: Int, code: Int) {
+        if (PKStateManager.roomState == PKStateManager.PK&&state==2&&code==0){
+            pkVm.pkSure(PKStateManager.pkId)
+        }
+    }
+
     /**************************PK******************************/
     private val marginTopValue by lazy {
         ImmersionBar.getStatusBarHeight(this) + DpPxUtil.dip2px(78f)
@@ -228,31 +246,38 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
 
     //对方主播id
     private var peerAnchorId = 0
-    override fun startPK(startPKModel: StartPKModel,isGetDataFromIM:Boolean) {
-        peerAnchorId = startPKModel.oppositeUserId.toInt()
-        AgoraManager.startPK(startPKModel.roomId,startPKModel.oppositeRoomId,startPKModel.userId.toInt(),startPKModel.sourceToken,startPKModel.destToken)
-        setPKLayoutParams(binding.flLocal,true)
-        AgoraManager.setupRemoteVideo(this@AnchorRoomActivity,peerAnchorId,binding.peerFl)
+    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
+            peerAnchorId = startPKModel.oppositeUserId.toInt()
+            AgoraManager.startPK(
+                startPKModel.roomId,
+                startPKModel.oppositeRoomId,
+                startPKModel.userId.toInt(),
+                startPKModel.sourceToken,
+                startPKModel.destToken
+            )
+            setPKLayoutParams(binding.flLocal, true)
+            AgoraManager.setupRemoteVideo(this@AnchorRoomActivity, peerAnchorId, binding.peerFl)
+
     }
 
     override fun stopPK(stopPKModel: StopPKModel) {
         AgoraManager.stopPK()
-        setPKLayoutParams(binding.flLocal,false)
-        AgoraManager.removeRemoteVideo(peerAnchorId,binding.peerFl)
+        setPKLayoutParams(binding.flLocal, false)
+        AgoraManager.removeRemoteVideo(peerAnchorId, binding.peerFl)
     }
 
-    override fun punishPK(punishPKModel: PunishPKModel,isGetDataFromIM:Boolean) {
+    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
 
     }
 
-    override fun processChangePK(processPKModel: ProcessPKModel) {
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
 
     }
 
 
     //设置视频画面大小
-    private fun setPKLayoutParams(view:View?,isPK:Boolean){
-        if (isPK){
+    private fun setPKLayoutParams(view: View?, isPK: Boolean) {
+        if (isPK) {
             val x = DpPxUtil.getScreenWidth() / 2
             val y = DpPxUtil.getScreenWidth() * 275 / 360
             val params = ConstraintLayout.LayoutParams(x, y)
@@ -262,7 +287,7 @@ class AnchorRoomActivity : AbsAnchorActivity<ActivityAnchorRoomBinding,IRoomInfo
             params.height = y
             params.topMargin = marginTopValue
             view?.layoutParams = params
-        }else{
+        } else {
             val params = ConstraintLayout.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
                 ViewGroup.LayoutParams.MATCH_PARENT

+ 51 - 0
room/src/main/java/com/swago/room/anchor/AnchorRoomFragment.kt

@@ -1,13 +1,21 @@
 package com.swago.room.anchor
 
 import com.swago.baseswago.PersonDataDFragment
+import com.swago.baseswago.agora.AgoraManager
 import com.swago.baseswago.baseroom.IRoomInfo
+import com.swago.baseswago.model.live.pk.ProcessPKModel
+import com.swago.baseswago.model.live.pk.PunishPKModel
+import com.swago.baseswago.model.live.pk.StartPKModel
+import com.swago.baseswago.model.live.pk.StopPKModel
 import com.swago.room.base.BaseComFragment
 import com.swago.room.databinding.FragmentBaseComBinding
 import com.swago.room.gift.GiftDialog
 import com.swago.room.hongbao.RedEnvelopeDialog
 import com.swago.room.inter.IFooter
 import com.swago.room.inter.IHeader
+import com.swago.room.pk.PKAcceptDialog
+import com.swago.room.pk.PKInviteDialog
+import com.swago.room.pk.PKSearchLisDialog
 import com.swago.room.widget.AnchorFooterView
 import com.swago.room.widget.ComHeaderView
 
@@ -18,6 +26,8 @@ import com.swago.room.widget.ComHeaderView
 class AnchorRoomFragment : BaseComFragment<FragmentBaseComBinding>() {
 
     private var footerView : AnchorFooterView? = null
+    private var pkAcceptDialog:PKAcceptDialog? = null
+    private var pkInviteDialog:PKInviteDialog? = null
 
     override fun initOther() {
         super.initOther()
@@ -32,12 +42,17 @@ class AnchorRoomFragment : BaseComFragment<FragmentBaseComBinding>() {
 
         footerView?.openMessageFun = {
             openMessageListDialog()
+            AgoraManager.setMute()
         }
 
         footerView?.openGameFun = {
             openGameDialog()
         }
 
+        footerView?.openPKFun = {
+            openPKSearchDialog()
+        }
+
 
         (iHeader as ComHeaderView).showUserInfo = {
             PersonDataDFragment.newInstance(it, isAnchor = true, inRoom = true)
@@ -55,6 +70,27 @@ class AnchorRoomFragment : BaseComFragment<FragmentBaseComBinding>() {
                 }.show(childFragmentManager,"PersonDataDFragment")
         }
 
+        pkVm.acceptFromSenderPKLiveData.observe(this){
+            pkAcceptDialog = PKAcceptDialog.newInstance(it)
+            pkAcceptDialog?.show(childFragmentManager,"PKAcceptDialog")
+        }
+
+        pkVm.acceptOrRefuseLiveData.observe(this){
+            if (it ==2){
+                pkAcceptDialog?.dismissAllowingStateLoss()
+            }else if(it ==3||it ==4||it ==5){
+                pkInviteDialog?.dismissAllowingStateLoss()
+            }
+        }
+    }
+
+    private fun openPKSearchDialog() {
+        PKSearchLisDialog.newInstance().apply {
+            openPKInviteFun = {
+                pkInviteDialog = PKInviteDialog.newInstance(it)
+                pkInviteDialog?.show(parentFragmentManager,"PKInviteDialog")
+            }
+        }.show(childFragmentManager,"PKSearchLisDialog")
     }
 
 
@@ -72,6 +108,21 @@ class AnchorRoomFragment : BaseComFragment<FragmentBaseComBinding>() {
     override fun endRoom(iRoomInfo: IRoomInfo?) {
     }
 
+
+    /*********************PK**************************/
+    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
+    }
+
+    override fun stopPK(stopPKModel: StopPKModel) {
+    }
+
+    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
+    }
+
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
+    }
+    /*********************PK**************************/
+
     override fun closeRoomed() {
         super.closeRoomed()
     }

+ 13 - 1
room/src/main/java/com/swago/room/base/BaseComFragment.kt

@@ -48,6 +48,9 @@ import com.swago.room.hongbao.RedEnvelopeDialog
 import com.swago.room.inter.IFooter
 import com.swago.room.inter.IHeader
 import com.swago.room.piaotiao.WaftManager
+import com.swago.room.pk.IPKListener
+import com.swago.room.pk.PKStateManager
+import com.swago.room.pk.PkVm
 import com.swago.room.vm.MsgVm
 import com.swago.room.vm.RoomOtherVm
 import com.swago.room.vm.RoomVm
@@ -64,10 +67,11 @@ import java.util.concurrent.CopyOnWriteArrayList
  *description:
  */
 abstract class BaseComFragment<T : FragmentBaseComBinding> : BaseXFragment<T>(),
-    IRoomActiveListener,
+    IRoomActiveListener,IPKListener,
     RoomTimer.TimeTickListener {
 
     val giftVm by activityViewModels<GiftVm>()
+    val pkVm by activityViewModels<PkVm>()
 
     val roomVm by activityViewModels<RoomVm>()
     val roomOtherVm by activityViewModels<RoomOtherVm>()
@@ -111,6 +115,7 @@ abstract class BaseComFragment<T : FragmentBaseComBinding> : BaseXFragment<T>(),
 
     override fun initOther() {
         RoomTimer.timeTickList.add(this)
+        PKStateManager.addPKListener(this)
         SwagoRoomManager.addListener(this)
         binding.headFl.addView(iHeader.getHeaderView())
         binding.footerFl.addView(iFooter.getFooterView())
@@ -142,6 +147,12 @@ abstract class BaseComFragment<T : FragmentBaseComBinding> : BaseXFragment<T>(),
         activity?.let {
             KeyboardUtils.registerSoftInputChangedListener(it.window, listener)
         }
+
+        binding.pkLayoutView.doGetPKInfoFun = {
+            SwagoRoomManager.iRoomInfo?.let {
+                pkVm.getPKInfo(it.getRoomId())
+            }
+        }
     }
 
     var listener = KeyboardUtils.OnSoftInputChangedListener {
@@ -322,6 +333,7 @@ abstract class BaseComFragment<T : FragmentBaseComBinding> : BaseXFragment<T>(),
 
     override fun onDestroyView() {
         super.onDestroyView()
+        PKStateManager.removePKListener(this)
         activity?.let {
             KeyboardUtils.unregisterSoftInputChangedListener(it.window)
         }

+ 2 - 1
room/src/main/java/com/swago/room/gift/GiftVm.kt

@@ -13,6 +13,7 @@ import com.swago.baseswago.util.AppContext
 import com.swago.baseswago.util.BaseViewModel
 import com.swago.baseswago.util.LogUtil
 import com.swago.baseswago.util.UserInfo
+import com.swago.room.pk.PKStateManager
 
 /**
  *@date 2021/12/12 17:03
@@ -56,7 +57,7 @@ class GiftVm(application: Application) : BaseViewModel(application) {
     ) {
         requestData2(false) {
             requestData {
-                val data = ApiManager.roomApi.sendGift(room_id, gift_id, gift_batch, gift_receive_id, isCombo,gift_num)
+                val data = ApiManager.roomApi.sendGift(room_id, gift_id, gift_batch, gift_receive_id, isCombo,gift_num,PKStateManager.pkId)
                 LogUtil.d("送礼","接口调用成功--${System.currentTimeMillis()}")
                 sendResultLiveData.value = data
                 UserInfo.getUserInfo()?.let {

+ 1 - 1
room/src/main/java/com/swago/room/pk/IPKListener.kt

@@ -17,5 +17,5 @@ interface IPKListener {
     fun punishPK(punishPKModel: PunishPKModel,isGetDataFromIM:Boolean)
 
     //PK进度条变更
-    fun processChangePK(processPKModel: ProcessPKModel)
+    fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM:Boolean)
 }

+ 55 - 2
room/src/main/java/com/swago/room/pk/PKAcceptDialog.kt

@@ -3,21 +3,31 @@ package com.swago.room.pk
 import android.os.Bundle
 import android.view.Gravity
 import androidx.fragment.app.viewModels
+import com.swago.baseswago.baseroom.RoomTimer
 import com.swago.baseswago.dialog.BaseXDFragment
+import com.swago.baseswago.model.live.pk.SendPKModel
+import com.swago.baseswago.util.AppContext
+import com.swago.baseswago.util.NoDoubleClickListener
+import com.swago.loadUrl
+import com.swago.room.R
 import com.swago.room.databinding.DialogPkAcceptBinding
 
-class PKAcceptDialog : BaseXDFragment<DialogPkAcceptBinding>() {
+class PKAcceptDialog : BaseXDFragment<DialogPkAcceptBinding>(), RoomTimer.TimeTickListener {
 
     private val pkVm by viewModels<PkVm>()
+    private var timeCount = 30
+    private var sendPKModel :SendPKModel? = null
 
     init {
         setGravity(Gravity.BOTTOM)
         setCanCancel(false)
+        setDimAmount(0f)
     }
 
     companion object{
-        fun newInstance(): PKAcceptDialog {
+        fun newInstance(sendPKModel: SendPKModel): PKAcceptDialog {
             val args = Bundle()
+            args.putParcelable("sendPKModel",sendPKModel)
             val fragment = PKAcceptDialog()
             fragment.arguments = args
             return fragment
@@ -25,11 +35,54 @@ class PKAcceptDialog : BaseXDFragment<DialogPkAcceptBinding>() {
     }
 
     override fun initOther() {
+        RoomTimer.timeTickList.add(this)
+        arguments?.let {
+            sendPKModel = it.getParcelable("sendPKModel")
+            sendPKModel?.apply {
+                context?.let { context ->
+                    binding.tvSelfName.text = this.receiverName
+                    binding.ivSelf.loadUrl(context,this.receiverAvatar)
 
+                    binding.tvPeerName.text = this.senderName
+                    binding.ivPeer.loadUrl(context,this.senderAvatar)
+
+                    binding.tvTitle.text = AppContext.getContext().resources.getString(R.string.invites_you_to_pk).format(this.senderName)
+                }
+            }
+
+            binding.tvAccept.setOnClickListener(object:NoDoubleClickListener(){
+                override fun onClick() {
+                    sendPKModel?.let {
+                        pkVm.acceptPKOrRefusePK(1,it.senderId)
+                        dismissAllowingStateLoss()
+                    }
+                }
+            })
+
+            binding.tvRefuse.setOnClickListener(object:NoDoubleClickListener(){
+                override fun onClick() {
+                    sendPKModel?.let {
+                        pkVm.acceptPKOrRefusePK(2,it.senderId)
+                        dismissAllowingStateLoss()
+                    }
+                }
+            })
+        }
     }
 
     override fun initLiveData() {
 
+    }
+
+    override fun onDestroyView() {
+        RoomTimer.timeTickList.remove(this)
+        super.onDestroyView()
+    }
 
+    override fun onTimeCount(time: Int) {
+        timeCount--
+        if (timeCount==0){
+            dismissAllowingStateLoss()
+        }
     }
 }

+ 12 - 0
room/src/main/java/com/swago/room/pk/PKAudienceAdapter.kt

@@ -13,6 +13,18 @@ class PKAudienceAdapter : BaseQuickAdapter<PKSeat,BaseViewHolder>(R.layout.item_
         helper?.apply {
             item?.let {
                 itemView.findViewById<CircleImageView>(R.id.ivAvatar).loadUrl(itemView.context,it.userAvatar)
+                when(layoutPosition){
+                    0 -> {
+                        setImageResource(R.id.ivPosition,R.mipmap.first)
+                    }
+                    1 -> {
+                        setImageResource(R.id.ivPosition,R.mipmap.second)
+                    }
+
+                    2 -> {
+                        setImageResource(R.id.ivPosition,R.mipmap.third)
+                    }
+                }
             }
         }
     }

+ 81 - 3
room/src/main/java/com/swago/room/pk/PKInviteDialog.kt

@@ -2,22 +2,33 @@ package com.swago.room.pk
 
 import android.os.Bundle
 import android.view.Gravity
+import android.view.View
 import androidx.fragment.app.viewModels
+import com.swago.baseswago.baseroom.RoomTimer
 import com.swago.baseswago.dialog.BaseXDFragment
+import com.swago.baseswago.model.live.pk.*
+import com.swago.baseswago.util.AppContext
+import com.swago.baseswago.util.NoDoubleClickListener
+import com.swago.baseswago.util.UserInfo
+import com.swago.loadUrl
+import com.swago.room.R
 import com.swago.room.databinding.DialogPkInviteBinding
 
-class PKInviteDialog : BaseXDFragment<DialogPkInviteBinding>() {
+class PKInviteDialog : BaseXDFragment<DialogPkInviteBinding>(), RoomTimer.TimeTickListener,IPKListener {
 
     private val pkVm by viewModels<PkVm>()
+    private var timeCount = 30
 
     init {
         setGravity(Gravity.BOTTOM)
-        setCanCancel(false)
+        setCanCancel(true)
+        setDimAmount(0f)
     }
 
     companion object{
-        fun newInstance(): PKInviteDialog {
+        fun newInstance(peerPKLiverModel:PKLiverModel): PKInviteDialog {
             val args = Bundle()
+            args.putParcelable("pkLiverModel",peerPKLiverModel)
             val fragment = PKInviteDialog()
             fragment.arguments = args
             return fragment
@@ -26,10 +37,77 @@ class PKInviteDialog : BaseXDFragment<DialogPkInviteBinding>() {
 
 
     override fun initOther() {
+        RoomTimer.timeTickList.add(this)
+        PKStateManager.addPKListener(this)
+        arguments?.let {
+           val peerPKLiverModel : PKLiverModel? =  it.getParcelable("pkLiverModel")
+            peerPKLiverModel?.apply {
+                binding.tvPeerName.text = this.user_name
+                context?.let { context ->
+                    binding.ivPeer.loadUrl(context,this.user_head_img_url)
 
+                    UserInfo.getUserInfo()?.let { userInfoModel ->
+                        binding.tvSelfName.text = userInfoModel.user_name
+                        binding.ivSelf.loadUrl(context,userInfoModel.user_head_img_url)
+                    }
+                }
+            }
+
+            binding.tvInvite.setOnClickListener(object:NoDoubleClickListener(){
+                override fun onClick() {
+                    peerPKLiverModel?.let {
+                        pkVm.invitePeerPK(it.id)
+                        binding.tvInvite.visibility = View.GONE
+                        binding.tvCancel.visibility = View.VISIBLE
+                    }
+                }
+            })
+
+            binding.tvCancel.setOnClickListener(object:NoDoubleClickListener(){
+                override fun onClick() {
+                    pkVm.cancelPK()
+                }
+            })
+        }
     }
 
     override fun initLiveData() {
+        pkVm.inviteSuccessLiveData.observe(this){
+            timeCount = 30
+            binding.tvTimeCount.visibility = View.VISIBLE
+            binding.tvTimeCount.text = AppContext.getContext().resources.getString(R.string.inviting_time).format(timeCount)
+        }
+
+        pkVm.cancelPKSuccessLiveData.observe(this){
+            binding.tvInvite.visibility = View.VISIBLE
+            binding.tvCancel.visibility = View.GONE
+            binding.tvTimeCount.visibility = View.GONE
+        }
+    }
+
+    override fun onDestroyView() {
+        PKStateManager.removePKListener(this)
+        RoomTimer.timeTickList.remove(this)
+        super.onDestroyView()
+    }
+
+    override fun onTimeCount(time: Int) {
+        timeCount--
+        if (timeCount>0){
+            binding.tvTimeCount.text = AppContext.getContext().resources.getString(R.string.inviting_time).format(timeCount)
+        }
+    }
+
+    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
+        dismissAllowingStateLoss()
+    }
+
+    override fun stopPK(stopPKModel: StopPKModel) {
+    }
+
+    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
+    }
 
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
     }
 }

+ 189 - 49
room/src/main/java/com/swago/room/pk/PKLayoutView.kt

@@ -20,8 +20,10 @@ import com.swago.baseswago.model.live.pk.ProcessPKModel
 import com.swago.baseswago.model.live.pk.PunishPKModel
 import com.swago.baseswago.model.live.pk.StartPKModel
 import com.swago.baseswago.model.live.pk.StopPKModel
+import com.swago.baseswago.util.AppContext
 import com.swago.baseswago.util.DpPxUtil
 import com.swago.baseswago.util.TimeUtil
+import com.swago.loadUrl
 import com.swago.room.R
 import com.swago.room.databinding.LayoutPkViewBinding
 import java.io.File
@@ -31,6 +33,7 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
 
     private var binding:LayoutPkViewBinding? = null
     private var svgParser:SVGAParser? = null
+    private var svgParserProgress:SVGAParser? = null
     private var mProgress = 50
     private val selfAdapter by lazy {
         PKAudienceAdapter()
@@ -43,6 +46,11 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
 
     var pkResult = 3
 
+    private var pkEndTime = 0
+
+    //主播获取PK信息
+    var doGetPKInfoFun:(()->Unit)? = null
+
     constructor(context: Context) : this(context, null)
     constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
     constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(
@@ -59,6 +67,8 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
         PKStateManager.addPKListener(this)
         RoomTimer.timeTickList.add(this)
         svgParser = SVGAParser(context)
+        svgParserProgress = SVGAParser(context)
+        playProgress("laugh.svga")
         binding?.let {
             it.rvSelf.layoutManager = LinearLayoutManager(context)
             it.rvSelf.adapter = selfAdapter
@@ -74,10 +84,23 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
         }
     }
 
+    private fun initProgressPosition(){
+        binding?.apply {
+            val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+            svgProcessLayoutParams.startToStart = R.id.view
+            svgProcessLayoutParams.topToBottom = R.id.view
+            svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+            svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/2
+            svgProgress.layoutParams = svgProcessLayoutParams
+        }
+
+    }
+
     override fun changeRoom(iRoomInfo: IRoomInfo) {
     }
 
     override fun leaveRoom(iRoomInfo: IRoomInfo) {
+        visibility = View.GONE
         resetSvg()
         resetData()
     }
@@ -95,16 +118,31 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
         PKStateManager.removePKListener(this)
     }
 
+    private var startPKModel:StartPKModel? = null
+
     override fun startPK(startPKModel: StartPKModel,isGetDataFromIM:Boolean) {
         binding?.apply {
+            this@PKLayoutView.startPKModel = startPKModel
+            pkEndTime = startPKModel.pkEndTime-startPKModel.pkResultTime
+            if (isGetDataFromIM){
+                initProgressPosition()
+            }
+            tvSelf.text = "0"
+            tvPeer.text = "0"
             visibility = View.VISIBLE
             pkTime = startPKModel.pkResultTime
             tvPkTime.text = TimeUtil.convertMinSecond(pkTime.toLong())
-            playProgress("file:///android_asset/progress.svga",2)
+            playProgress("progress.svga")
             clPKTime.visibility = View.VISIBLE
             clPunishTime.visibility = View.GONE
+            tvPeerName.text = startPKModel.oppositeName
+            tvPeerId.text = AppContext.getContext().resources.getString(R.string.id_x).format(startPKModel.oppositeUserId)
+            try {
+                ivPeerAvatar.loadUrl(context,startPKModel.oppositeAvatar)
+            }catch (e:Exception){
+                e.printStackTrace()
+            }
         }
-
     }
 
     override fun stopPK(stopPKModel: StopPKModel) {
@@ -114,30 +152,41 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
 
     override fun punishPK(punishPKModel: PunishPKModel,isGetDataFromIM:Boolean) {
         binding?.apply {
+            if (!isGetDataFromIM){
+                ivPeerAvatar.loadUrl(context,punishPKModel.oppositeAvatar)
+                tvPeerName.text = punishPKModel.oppositeName
+                tvPeerId.text = AppContext.getContext().resources.getString(R.string.id_x).format(punishPKModel.oppositeUserId)
+            }else{
+                startPKModel?.let {
+                    pkTime = it.pkEndTime - it.pkResultTime
+                }
+            }
             visibility = View.VISIBLE
             clPKTime.visibility = View.GONE
             clPunishTime.visibility = View.VISIBLE
             if (svgProgress.isAnimating){
                 svgProgress.stopAnimation()
             }
-            // 1赢 2输 3平局
+            // 3赢 4输  5平局
             pkResult =punishPKModel.roomResult
             when(punishPKModel.roomResult){
-                1 -> {
-                    playProgress("file:///android_asset/pk_win.svga",1)
+                3 -> {
+                    playPKResultSvg("pk_win.svga")
+                    playProgress("laugh.svga")
                 }
-                2 -> {
-                    playProgress("file:///android_asset/pk_fail.svga",1)
+                4 -> {
+                    playPKResultSvg("pk_fail.svga")
+                    playProgress("cry.svga")
                 }
-                3 -> {
-                    playProgress("file:///android_asset/pk_balance.svga",1)
+                5 -> {
+                    playPKResultSvg("pk_balance.svga")
                 }
             }
 
         }
     }
 
-    override fun processChangePK(processPKModel: ProcessPKModel) {
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
         binding?.apply {
             if (processPKModel.roomAudienceList.isNotEmpty()){
                 selfAdapter.setNewData(processPKModel.roomAudienceList)
@@ -145,14 +194,17 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
             if (processPKModel.oppositeRoomAudienceList.isNotEmpty()){
                 peerAdapter.setNewData(processPKModel.oppositeRoomAudienceList)
             }
-
-            if (tvSelf.text.toString().toInt() < processPKModel.progressValue || tvPeer.text.toString().toInt() < processPKModel.oppositeProgressValue) {
+            if (!isGetDataFromIM){
                 tvSelf.text = processPKModel.progressValue.toString()
                 tvPeer.text = processPKModel.oppositeProgressValue.toString()
-            } else {
-                return
+            }else{
+                if (tvSelf.text.toString().toInt() < processPKModel.progressValue || tvPeer.text.toString().toInt() < processPKModel.oppositeProgressValue) {
+                    tvSelf.text = processPKModel.progressValue.toString()
+                    tvPeer.text = processPKModel.oppositeProgressValue.toString()
+                } else {
+                    return
+                }
             }
-
             val selfProgressValue = if (processPKModel.progressValue == 0) {
                  0.01
             } else {
@@ -177,11 +229,74 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
             progressBar.progress = mProgress
 
 
-            val svgProcessLayoutParams = ConstraintLayout.LayoutParams(WRAP_CONTENT,DpPxUtil.dip2px(15f))
-            svgProcessLayoutParams.startToStart = R.id.svgProgress
-            svgProcessLayoutParams.topToTop = R.id.svgProgress
-            svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress
-            svgProgress.layoutParams = svgProcessLayoutParams
+            if (isGetDataFromIM){
+                if (processPKModel.progressValue == 0&&processPKModel.oppositeProgressValue != 0){
+                    val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                    svgProcessLayoutParams.startToStart = R.id.view
+                    svgProcessLayoutParams.topToBottom = R.id.view
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/10 - DpPxUtil.dip2px(10f)
+                    svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                    svgProgress.layoutParams = svgProcessLayoutParams
+                    return
+                }
+
+                if (processPKModel.oppositeProgressValue == 0&&processPKModel.progressValue != 0){
+                    val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                    svgProcessLayoutParams.startToStart = R.id.view
+                    svgProcessLayoutParams.topToBottom = R.id.view
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/10*9 - DpPxUtil.dip2px(10f)
+                    svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                    svgProgress.layoutParams = svgProcessLayoutParams
+                    return
+                }
+
+                val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                svgProcessLayoutParams.startToStart = R.id.view
+                svgProcessLayoutParams.topToBottom = R.id.view
+                if (mProgress>50){
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress + DpPxUtil.dip2px(10f)
+                }else if(mProgress<50){
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress - DpPxUtil.dip2px(10f)
+                }else{
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress
+                }
+
+                svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                svgProgress.layoutParams = svgProcessLayoutParams
+            }else{
+                if (processPKModel.progressValue == 0&&processPKModel.oppositeProgressValue != 0){
+                    val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                    svgProcessLayoutParams.startToStart = R.id.view
+                    svgProcessLayoutParams.topToBottom = R.id.view
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/10 - DpPxUtil.dip2px(10f)
+                    svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                    svgProgress.layoutParams = svgProcessLayoutParams
+                    return
+                }
+
+                if (processPKModel.oppositeProgressValue == 0&&processPKModel.progressValue != 0){
+                    val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                    svgProcessLayoutParams.startToStart = R.id.view
+                    svgProcessLayoutParams.topToBottom = R.id.view
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/10*9 - DpPxUtil.dip2px(10f)
+                    svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                    svgProgress.layoutParams = svgProcessLayoutParams
+                    return
+                }
+
+                val svgProcessLayoutParams = ConstraintLayout.LayoutParams(DpPxUtil.dip2px(20f),DpPxUtil.dip2px(20f))
+                svgProcessLayoutParams.startToStart = R.id.view
+                svgProcessLayoutParams.topToBottom = R.id.view
+                if (mProgress>50){
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress + DpPxUtil.dip2px(10f)
+                }else if(mProgress<50){
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress - DpPxUtil.dip2px(10f)
+                }else{
+                    svgProcessLayoutParams.marginStart = DpPxUtil.getScreenWidth()/100*mProgress
+                }
+                svgProcessLayoutParams.topMargin = DpPxUtil.dip2px(-3f)
+                svgProgress.layoutParams = svgProcessLayoutParams
+            }
 
         }
     }
@@ -190,9 +305,19 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
         binding?.apply {
             pkTime--
             if (PKStateManager.roomState==PKStateManager.PK){
-                tvPkTime.text = TimeUtil.convertMinSecond(pkTime.toLong())
+                if (pkTime>=0){
+                    tvPkTime.text = TimeUtil.convertMinSecond(pkTime.toLong())
+                }
+                if (pkTime==-5 ){
+                    doGetPKInfoFun?.invoke()
+                }
             }else if(PKStateManager.roomState==PKStateManager.PUNISH){
-                tvPunishTime.text = TimeUtil.convertMinSecond(pkTime.toLong())
+                if (pkTime>=0){
+                    tvPunishTime.text = TimeUtil.convertMinSecond(pkTime.toLong())
+                }
+                if (pkTime==-5 ){
+                    doGetPKInfoFun?.invoke()
+                }
             }
         }
     }
@@ -232,37 +357,49 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
     /**
      * type 1 播放PK结果动画  2 播放正在PK进度条动画
      */
-    private fun playProgress(path:String,type:Int){
-        svgParser?.let {
+    private fun playProgress(path:String){
+        svgParserProgress?.let {
             it.decodeFromAssets(path,object:SVGAParser.ParseCompletion{
                 override fun onComplete(videoItem: SVGAVideoEntity) {
                     binding?.apply {
                         val drawable = SVGADrawable(videoItem)
-                        when(type){
-                            1 -> {
-                                svgPKResult.setImageDrawable(drawable)
-                                svgPKResult.callback = callback
-                                svgPKResult.visibility = View.VISIBLE
-                                svgPKResult.loops = 1
-                                svgPKResult.startAnimation()
-                            }
-
-                            2 -> {
-                                svgProgress.setImageDrawable(drawable)
-                                svgProgress.callback = callback
-                                svgProgress.visibility = View.VISIBLE
-                                svgProgress.loops = 99999
-                                svgProgress.startAnimation()
-                            }
-                        }
+                        svgProgress.setImageDrawable(drawable)
+                        svgProgress.loops = 99999
+                        svgProgress.startAnimation()
+                    }
+                }
 
+                override fun onError() {
+                    binding?.apply {
                     }
+                }
+            },object:SVGAParser.PlayCallback{
+                override fun onPlay(file: List<File>) {
+                }
+
+            })
+
+        }
+    }
 
+
+    private fun playPKResultSvg(path:String){
+        svgParser?.let {
+            it.decodeFromAssets(path,object:SVGAParser.ParseCompletion{
+                override fun onComplete(videoItem: SVGAVideoEntity) {
+                    binding?.apply {
+                        val drawable = SVGADrawable(videoItem)
+                        svgPKResult.setImageDrawable(drawable)
+                        svgPKResult.callback = playResultCallback
+                        svgPKResult.visibility = View.VISIBLE
+                        svgPKResult.loops = 1
+                        svgPKResult.startAnimation()
+                    }
                 }
 
                 override fun onError() {
                     binding?.apply {
-                        svgProgress.visibility = View.GONE
+                        svgPKResult.visibility = View.GONE
                     }
                 }
             },object:SVGAParser.PlayCallback{
@@ -274,23 +411,26 @@ class PKLayoutView : ConstraintLayout, IRoomActiveListener, IPKListener,
         }
     }
 
-    private var callback = object: SVGACallback {
+
+    private var playResultCallback = object: SVGACallback {
 
         override fun onFinished() {
             binding?.apply {
-                svgProgress.visibility = View.GONE
-                ivSelfPKResult.visibility = View.VISIBLE
-                ivPeerPKResult.visibility = View.VISIBLE
+               if (PKStateManager.roomState == PKStateManager.PUNISH){
+                   ivSelfPKResult.visibility = View.VISIBLE
+                   ivPeerPKResult.visibility = View.VISIBLE
+               }
+                svgPKResult.visibility = View.GONE
                 when(pkResult){
-                    1 -> {
+                    3 -> {
                         ivSelfPKResult.setImageResource(R.mipmap.icon_pk_win)
                         ivPeerPKResult.setImageResource(R.mipmap.icon_pk_fail)
                     }
-                    2 -> {
+                    4 -> {
                         ivSelfPKResult.setImageResource(R.mipmap.icon_pk_fail)
                         ivPeerPKResult.setImageResource(R.mipmap.icon_pk_win)
                     }
-                    3 -> {
+                    5 -> {
                         ivSelfPKResult.setImageResource(R.mipmap.icon_pk_draw)
                         ivPeerPKResult.setImageResource(R.mipmap.icon_pk_draw)
                     }

+ 28 - 2
room/src/main/java/com/swago/room/pk/PKListAdapter.kt

@@ -2,11 +2,37 @@ package com.swago.room.pk
 
 import com.chad.library.adapter.base.BaseQuickAdapter
 import com.chad.library.adapter.base.BaseViewHolder
+import com.swago.baseswago.cusview.SwagoLevelView
+import com.swago.baseswago.model.live.pk.PKLiverModel
+import com.swago.baseswago.util.AppContext
+import com.swago.loadUrl
 import com.swago.room.R
+import de.hdodenhof.circleimageview.CircleImageView
 
-class PKListAdapter : BaseQuickAdapter<String,BaseViewHolder>(R.layout.item_pk_search, arrayListOf()) {
+class PKListAdapter : BaseQuickAdapter<PKLiverModel,BaseViewHolder>(R.layout.item_pk_search, arrayListOf()) {
 
-    override fun convert(helper: BaseViewHolder?, item: String?) {
+    override fun convert(helper: BaseViewHolder?, item: PKLiverModel?) {
+        helper?.apply {
+            item?.let {
+                setText(R.id.tvName,it.user_name)
 
+                val ivAvatar = itemView.findViewById<CircleImageView>(R.id.ivAvatar)
+                ivAvatar.loadUrl(itemView.context,it.user_head_img_url)
+                val tvLevel = itemView.findViewById<SwagoLevelView>(R.id.tvLevel)
+                tvLevel.setUserLevel(it.user_level)
+
+                if (it.user_sex==0){
+                    setImageResource(R.id.ivSex,R.mipmap.male)
+                }else{
+                    setImageResource(R.id.ivSex,R.mipmap.female)
+                }
+
+                setText(R.id.tvID,AppContext.getContext().resources.getString(R.string.id_x).format(it.id))
+                setText(R.id.tvFans,AppContext.getContext().resources.getString(R.string.fans_x).format(it.user_fans_num))
+
+                addOnClickListener(R.id.tvPK)
+
+            }
+        }
     }
 }

+ 54 - 16
room/src/main/java/com/swago/room/pk/PKSearchLisDialog.kt

@@ -1,51 +1,89 @@
 package com.swago.room.pk
 
+import android.os.Bundle
 import android.view.Gravity
+import androidx.core.widget.addTextChangedListener
 import androidx.fragment.app.viewModels
 import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.chad.library.adapter.base.BaseQuickAdapter
+import com.swago.baseswago.cusview.SwagoRecyclerView
+import com.swago.baseswago.dialog.BaseListDialogFragment
 import com.swago.baseswago.dialog.BaseXDFragment
+import com.swago.baseswago.model.live.RoomUserModel
+import com.swago.baseswago.model.live.pk.PKLiverModel
+import com.swago.baseswago.util.LogUtil
 import com.swago.baseswago.util.NoDoubleClickListener
 import com.swago.room.databinding.DialogPkSearchBinding
 
-class PKSearchLisDialog : BaseXDFragment<DialogPkSearchBinding>() {
+class PKSearchLisDialog : BaseListDialogFragment<DialogPkSearchBinding,PKLiverModel>() {
 
     private val pkVm by viewModels<PkVm>()
 
-    private val adapter by lazy {
-        PKListAdapter()
-    }
+    var openPKInviteFun:((pkLiverModel:PKLiverModel)->Unit)? =null
 
     init {
         setGravity(Gravity.BOTTOM)
         setCanCancel(true)
+        setDimAmount(0f)
+    }
+
+    companion object{
+        fun newInstance(): PKSearchLisDialog {
+            val args = Bundle()
+            val fragment = PKSearchLisDialog()
+            fragment.arguments = args
+            return fragment
+        }
     }
 
-    override fun initOther() {
-        //TODO 默认可PK主播列表
+    override val smartRecyclerView: SwagoRecyclerView<PKLiverModel> by lazy {
+        binding.rvPKList as SwagoRecyclerView<PKLiverModel>
+    }
+    override val adapter: BaseQuickAdapter<PKLiverModel, *> by lazy {
+        PKListAdapter()
+    }
 
+    override val layoutManager: RecyclerView.LayoutManager by lazy {
+        LinearLayoutManager(context)
+    }
+    override val loadData: (page: Int) -> Unit = {
+        pkVm.getDefault()
+    }
 
+    override fun initViewData() {
         binding.ivSearch.setOnClickListener(object:NoDoubleClickListener(){
             override fun onClick() {
                 val content = binding.etEdit.text.toString()
-                pkVm.searchAnchor(content)
+                pkVm.getDefault(content)
             }
         })
 
-        context?.let {
-            binding.rvPKList.layoutManager = LinearLayoutManager(it)
-            binding.rvPKList.adapter = adapter
-
-            adapter.setOnItemChildClickListener { adapter, view, position ->
-
+        binding.etEdit.addTextChangedListener {
+            it?.let {
+                if (it.toString().isEmpty()){
+                    pkVm.getDefault()
+                }
             }
         }
 
-
-
+        adapter.setOnItemChildClickListener { _, _, position ->
+            openPKInviteFun?.invoke(adapter.data[position])
+            dismissAllowingStateLoss()
+        }
     }
 
     override fun initLiveData() {
+        pkVm.liveModelListLiveData.observe(this){
+            if (it == null){
+                smartRecyclerView.onFetchDataError()
+            }else{
+                smartRecyclerView.onFetchDataFinish(it,true)
+            }
+        }
+    }
 
-
+    override fun loadMoreNeed(): Boolean {
+        return false
     }
 }

+ 8 - 0
room/src/main/java/com/swago/room/pk/PKStateManager.kt

@@ -9,6 +9,14 @@ object PKStateManager {
 
     var roomState = 1
 
+    //PK场次
+    var pkId = "0"
+
+
+    fun resetData(){
+        roomState = LIVING
+        pkId = "0"
+    }
 
     val pkIPKListenerList = ArrayList<IPKListener>()
 

+ 207 - 25
room/src/main/java/com/swago/room/pk/PkVm.kt

@@ -1,26 +1,220 @@
 package com.swago.room.pk
 
 import android.app.Application
+import android.widget.Toast
+import androidx.lifecycle.MutableLiveData
 import com.swago.baseswago.baseroom.IRoomInfo
 import com.swago.baseswago.baseroom.SwagoRoomManager
 import com.swago.baseswago.baseroom.viewmodel.AbsMsgVm
 import com.swago.baseswago.im.ImConstant
+import com.swago.baseswago.inter.ApiManager
 import com.swago.baseswago.model.im.CusNewMsgBean
 import com.swago.baseswago.model.im.RoomChatMsgBean
 import com.swago.baseswago.model.live.pk.*
+import com.swago.baseswago.util.AppContext
 import com.swago.baseswago.util.UserInfo
+import com.swago.room.R
 
 class PkVm(application: Application) : AbsMsgVm(application) {
     //接口调用
 
+    /**
+     * pK搜索对应主播
+     * 默认主播列表 不传参
+     */
+    val liveModelListLiveData by lazy {
+        MutableLiveData<List<PKLiverModel>?>()
+    }
+
+    fun getDefault(search_keyword: String = "") {
+        requestData2 {
+            requestData {
+                val data = ApiManager.roomApi.getPKLiverList(search_keyword)
+                liveModelListLiveData.value = data.list
+            }
+
+            requestError {
+                liveModelListLiveData.value = null
+            }
+        }
+    }
+
+
+    /**
+     * 主播发起邀请
+     */
+    val inviteSuccessLiveData by lazy {
+        MutableLiveData<Int>()
+    }
+    private var inviteCount = 0
+    fun invitePeerPK(pk_user_id: String) {
+        requestData {
+            ApiManager.roomApi.invitePK(pk_user_id)
+            inviteSuccessLiveData.value = inviteCount++
+        }
+    }
+
+
+    /**
+     * 主播主动取消PK
+     */
+    val cancelPKSuccessLiveData by lazy {
+        MutableLiveData<Int>()
+    }
+    private var cancelCount = 0
+    fun cancelPK() {
+        requestData {
+            ApiManager.roomApi.cancelInvitePK()
+            cancelPKSuccessLiveData.value = cancelCount
+        }
+    }
+
+    /**
+     * 主播接受PK邀请
+     */
+    fun acceptPKOrRefusePK(type: Int, userId: String) {
+        requestData {
+            ApiManager.roomApi.acceptRefusePK(type, userId)
+        }
+    }
+
+    /**
+     * 获取PK信息接口
+     */
+    fun getPKInfo(roomId: String) {
+        requestData {
+            //| 1直播 2正在PK 3赢 4输  5平局 |
+            val data = ApiManager.roomApi.getPKInfo(roomId)
+            when (data.roomState) {
+                1 -> {
+                    if (PKStateManager.roomState != PKStateManager.LIVING) {
+                        PKStateManager.roomState = PKStateManager.LIVING
+                        PKStateManager.pkId = "0"
+                        PKStateManager.pkIPKListenerList.forEach { ipkListener ->
+                            val stopPKModel = StopPKModel()
+                            stopPKModel.roomId = roomId
+                            ipkListener.stopPK(stopPKModel)
+                        }
+                    }
+                }
+                2 -> {
+                    if (PKStateManager.roomState != PKStateManager.PK) {
+                        PKStateManager.roomState = PKStateManager.PK
+                        PKStateManager.pkId = data.pkId
+                        PKStateManager.pkIPKListenerList.forEach { ipkListener ->
+                            val startPKModel = StartPKModel()
+                            startPKModel.oppositeUserId = data.oppositeUserId
+                            startPKModel.roomId = data.roomId
+                            startPKModel.pkResultTime = data.pkResultTime
+                            startPKModel.destToken = ""
+                            startPKModel.sourceToken = ""
+                            startPKModel.userId = data.userId
+                            startPKModel.oppositeAvatar = data.oppositeAvatar
+                            startPKModel.oppositeName = data.oppositeUserName
+                            startPKModel.oppositeRoomId = data.oppositeRoomId
+                            startPKModel.pkEndTime = startPKModel.pkEndTime
+                            startPKModel.pkId = data.pkId
+                            ipkListener.startPK(startPKModel, false)
+
+                            val processPKModel = ProcessPKModel(
+                                data.roomId,
+                                data.progressValue,
+                                data.roomAudienceList,
+                                data.oppositeRoomId,
+                                data.oppositeProgressValue,
+                                data.oppositeRoomAudienceList
+                            )
+                            ipkListener.processChangePK(processPKModel, false)
+                        }
+                    }
+                }
+                3, 4, 5 -> {
+                    if (PKStateManager.roomState != PKStateManager.PUNISH) {
+                        PKStateManager.roomState = PKStateManager.PUNISH
+                        PKStateManager.pkId = data.pkId
+                        PKStateManager.pkIPKListenerList.forEach { ipkListener ->
+                            val punishPKModel = PunishPKModel()
+                            punishPKModel.oppositeUserId = data.oppositeUserId
+                            punishPKModel.roomResult = data.roomResult
+                            punishPKModel.oppositeName = data.oppositeUserName
+                            punishPKModel.oppositeAvatar = data.oppositeAvatar
+                            punishPKModel.roomId = data.roomId
+                            punishPKModel.oppositeRoomId = data.oppositeRoomId
+                            punishPKModel.oppositeRoomResult = data.oppositeRoomResult
+                            punishPKModel.pkId = data.pkId
+                            punishPKModel.userId = data.userId
+                            ipkListener.punishPK(punishPKModel, false)
+
+                            val processPKModel = ProcessPKModel(
+                                data.roomId,
+                                data.progressValue,
+                                data.roomAudienceList,
+                                data.oppositeRoomId,
+                                data.oppositeProgressValue,
+                                data.oppositeRoomAudienceList
+                            )
+                            ipkListener.processChangePK(processPKModel, false)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * PK确认
+     */
+    fun pkSure(pkId: String) {
+        requestData {
+            ApiManager.roomApi.pkSure(pkId)
+        }
+    }
+
+
+    val acceptOrRefuseLiveData by lazy {
+        MutableLiveData<Int>()
+    }
+    val acceptFromSenderPKLiveData by lazy {
+        MutableLiveData<SendPKModel>()
+    }
 
     override fun receiveMsg() {
         imGroupNewMsgListener.handleMsgType<CusNewMsgBean<SendPKModel>>(ImConstant.pk_send) {
             it.data?.let {
                 UserInfo.getUserInfo()?.apply {
-                    if (this.id == it.receiverId){
-                        when(it.actionType){
-
+                    //1(发起PK) 2(发送方取消PK) 3(拒绝PK) 4(接受PK) 5(自动拒绝PK)
+                    when (it.actionType) {
+                        1 -> {
+                            if (this.id == it.receiverId) {
+                                //接收方收到对方发起的PK邀请
+                                acceptFromSenderPKLiveData.value = it
+                            }
+                        }
+                        2 -> {
+                            if (this.id == it.receiverId) {
+                                //接收方收到对方取消PK的邀请
+                                Toast.makeText(
+                                    AppContext.getContext(),
+                                    AppContext.getContext()
+                                        .getString(R.string.send_pk_liver_cancel),
+                                    Toast.LENGTH_SHORT
+                                ).show()
+                                acceptOrRefuseLiveData.value = it.actionType
+                            }
+                        }
+                        3, 4, 5 -> {
+                            if (this.id == it.senderId) {
+                                if (it.actionType == 3 || it.actionType == 5) {
+                                    Toast.makeText(
+                                        AppContext.getContext(),
+                                        AppContext.getContext()
+                                            .getString(R.string.peer_liver_refuse_pk),
+                                        Toast.LENGTH_SHORT
+                                    ).show()
+                                }
+                                acceptOrRefuseLiveData.value = it.actionType
+                            }
                         }
                     }
                 }
@@ -33,6 +227,7 @@ class PkVm(application: Application) : AbsMsgVm(application) {
                     if (this.getRoomId() == it.roomId) {
                         if (PKStateManager.roomState != PKStateManager.PK) {
                             PKStateManager.roomState = PKStateManager.PK
+                            PKStateManager.pkId = it.pkId
                             PKStateManager.pkIPKListenerList.forEach { ipkListener ->
                                 ipkListener.startPK(it, true)
                             }
@@ -46,9 +241,9 @@ class PkVm(application: Application) : AbsMsgVm(application) {
         imGroupNewMsgListener.handleMsgType<CusNewMsgBean<ProcessPKModel>>(ImConstant.pk_process) {
             it.data?.let {
                 SwagoRoomManager.iRoomInfo?.apply {
-                    if (this.getRoomId() == it.roomId){
+                    if (this.getRoomId() == it.roomId) {
                         PKStateManager.pkIPKListenerList.forEach { ipkListener ->
-                            ipkListener.processChangePK(it)
+                            ipkListener.processChangePK(it, true)
                         }
                     }
                 }
@@ -58,11 +253,12 @@ class PkVm(application: Application) : AbsMsgVm(application) {
         imGroupNewMsgListener.handleMsgType<CusNewMsgBean<PunishPKModel>>(ImConstant.pk_punish) {
             it.data?.let {
                 SwagoRoomManager.iRoomInfo?.apply {
-                    if (this.getRoomId() == it.roomId){
-                        if (PKStateManager.roomState !=PKStateManager.PUNISH){
+                    if (this.getRoomId() == it.roomId) {
+                        if (PKStateManager.roomState != PKStateManager.PUNISH) {
                             PKStateManager.roomState = PKStateManager.PUNISH
+                            PKStateManager.pkId = it.pkId
                             PKStateManager.pkIPKListenerList.forEach { ipkListener ->
-                                ipkListener.punishPK(it,true)
+                                ipkListener.punishPK(it, true)
                             }
                         }
                     }
@@ -73,9 +269,10 @@ class PkVm(application: Application) : AbsMsgVm(application) {
         imGroupNewMsgListener.handleMsgType<CusNewMsgBean<StopPKModel>>(ImConstant.pk_stop) {
             it.data?.let {
                 SwagoRoomManager.iRoomInfo?.apply {
-                    if (this.getRoomId() == it.roomId){
-                        if (PKStateManager.roomState !=PKStateManager.LIVING){
+                    if (this.getRoomId() == it.roomId) {
+                        if (PKStateManager.roomState != PKStateManager.LIVING) {
                             PKStateManager.roomState = PKStateManager.LIVING
+                            PKStateManager.pkId = "0"
                             PKStateManager.pkIPKListenerList.forEach { ipkListener ->
                                 ipkListener.stopPK(it)
                             }
@@ -100,19 +297,4 @@ class PkVm(application: Application) : AbsMsgVm(application) {
 
     override fun closeRoomed() {
     }
-
-
-    /**
-     * pK搜索对应主播
-     */
-    fun searchAnchor(content: String) {
-
-    }
-
-    /**
-     * 默认主播列表
-     */
-    fun getDefault() {
-
-    }
 }

+ 102 - 13
room/src/main/java/com/swago/room/user/UserRoomActivity.kt

@@ -9,12 +9,15 @@ import android.widget.FrameLayout
 import android.widget.ImageView
 import android.widget.Toast
 import androidx.activity.viewModels
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.lifecycle.lifecycleScope
 import androidx.viewpager.widget.ViewPager
 import com.alibaba.android.arouter.facade.annotation.Autowired
 import com.alibaba.android.arouter.facade.annotation.Route
 import com.alibaba.android.arouter.launcher.ARouter
 import com.bumptech.glide.Glide
 import com.bumptech.glide.request.RequestOptions
+import com.gyf.immersionbar.ImmersionBar
 import com.swago.baseswago.SwagoAdapter
 import com.swago.baseswago.UserVm
 import com.swago.baseswago.agora.AgoraManager
@@ -26,19 +29,25 @@ import com.swago.baseswago.baseroom.ui.AbsUserActivity
 import com.swago.baseswago.constant.ARouteConstant
 import com.swago.baseswago.databinding.ActivityAbsRoomUserBinding
 import com.swago.baseswago.model.MomentModel
-import com.swago.baseswago.util.AppContext
-import com.swago.baseswago.util.LogUtil
-import com.swago.baseswago.util.NoDoubleClickListener
-import com.swago.baseswago.util.UserInfo
+import com.swago.baseswago.model.live.pk.ProcessPKModel
+import com.swago.baseswago.model.live.pk.PunishPKModel
+import com.swago.baseswago.model.live.pk.StartPKModel
+import com.swago.baseswago.model.live.pk.StopPKModel
+import com.swago.baseswago.util.*
 import com.swago.room.R
 import com.swago.room.base.NoContentFragment
 import com.swago.room.bean.UserRoomModel
 import com.swago.room.data.RoomDataManager
+import com.swago.room.pk.IPKListener
+import com.swago.room.pk.PKStateManager
+import com.swago.room.pk.PkVm
 import com.swago.room.vm.MsgVm
 import com.swago.room.vm.RoomOtherVm
 import com.swago.room.vm.RoomVm
 import com.swago.room.widget.UserShowAnchorCloseView
 import jp.wasabeef.glide.transformations.BlurTransformation
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
 import java.util.concurrent.CopyOnWriteArrayList
 
 /**
@@ -47,12 +56,13 @@ import java.util.concurrent.CopyOnWriteArrayList
  */
 @Route(path = ARouteConstant.Room.user)
 class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomModel>(),
-    ISwagoIRtcEngineEventHandler {
+    ISwagoIRtcEngineEventHandler,IPKListener {
 
     private val roomVm by viewModels<RoomVm>()
     private val msgVm by viewModels<MsgVm>()
     private val userVm by viewModels<UserVm>()
     private val roomOtherVm by viewModels<RoomOtherVm>()
+    private val pkVm by viewModels<PkVm>()
 
     private val fragments = arrayListOf(NoContentFragment(), UserRoomFragment())
 
@@ -72,6 +82,7 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
     private var ivCover: ImageView? = null
     private var userShowAnchorCloseView: UserShowAnchorCloseView? = null
     private var flRoot: FrameLayout? = null
+    private var peerFl: FrameLayout? = null
 
     override val roomCoverView: ViewGroup by lazy {
         val userRoomView = layoutInflater.inflate(R.layout.layout_user_room, null) as ViewGroup
@@ -80,6 +91,7 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
         userShowAnchorCloseView = userRoomView.findViewById(R.id.userShowAnchorCloseView)
         ivCover = userRoomView.findViewById(R.id.ivCover)
         flRoot = userRoomView.findViewById(R.id.flRoot)
+        peerFl = userRoomView.findViewById(R.id.peerFl)
         viewPager.adapter = adapter
         viewPager.currentItem = 1
         userRoomView
@@ -89,18 +101,19 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
     override var mCurrentPosition: Int = position
     override var iRoomInfos: CopyOnWriteArrayList<UserRoomModel> = RoomDataManager.data
 
-    override fun initOther() {
+    override fun initUserRoomView() {
+        PKStateManager.resetData()
+        PKStateManager.addPKListener(this)
         AgoraManager.initializeEngine(this, this)
         ARouter.getInstance().inject(this)
         mCurrentPosition = position
         RoomDataManager.initData(data)
-        super.initOther()
         userRoomFragment = fragments[1] as UserRoomFragment
-    }
 
-    override fun initUserRoomView() {
         roomVm.init()
         msgVm.init()
+        pkVm.init()
+        initPeerAnchorLayoutParams()
         window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
 
         AgoraManager.setVideoConfiguration()
@@ -113,9 +126,6 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
         })
     }
 
-    override fun loadData() {
-    }
-
     override fun initLiveData() {
         msgVm.anchorRoomClosed = {
             userShowAnchorCloseView?.visibility = View.VISIBLE
@@ -158,12 +168,21 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
     }
 
     override fun leaveRoom(iRoomInfo: IRoomInfo) {
-        AgoraManager.changeRoom(iRoomInfo.getAnchorId().toInt(), flRoot)
+        setPKLayoutParams(flRoot,false)
+        if (PKStateManager.roomState == PKStateManager.LIVING) {
+            AgoraManager.changeRoom(iRoomInfo.getAnchorId().toInt(), flRoot)
+        } else {
+            AgoraManager.changeRoom(iRoomInfo.getAnchorId().toInt(), flRoot)
+            AgoraManager.changeRoom(peerAnchorId, peerFl)
+        }
+        PKStateManager.resetData()
     }
 
     override fun joinedRoom(iRoomInfo: IRoomInfo) {
         if (iRoomInfo.getIsRobot()) {
             ivCover?.visibility = View.GONE
+        }else{
+            pkVm.getPKInfo(iRoomInfo.getRoomId())
         }
         UserInfo.getUserInfo()?.let { userInfoModel ->
             AgoraManager.joinChannel(
@@ -194,6 +213,7 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
     }
 
     override fun onDestroy() {
+        PKStateManager.removePKListener(this)
         super.onDestroy()
     }
 
@@ -208,6 +228,8 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
         LogUtil.d("网络变更", "$state----$reason")
     }
 
+    override fun onChannelMediaRelayStateChanged(state: Int, code: Int) {}
+
     fun gotoTargetRoom(anchorId: String) {
         iRoomInfos.forEachIndexed { index, userRoomModel ->
             if (userRoomModel?.momentModel != null) {
@@ -219,4 +241,71 @@ class UserRoomActivity : AbsUserActivity<ActivityAbsRoomUserBinding, UserRoomMod
         }
         roomVm.getMomentModel(anchorId)
     }
+
+    private var peerAnchorId = 0
+    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
+        lifecycleScope.launch(Dispatchers.Main){
+            peerAnchorId = startPKModel.oppositeUserId.toInt()
+            setPKLayoutParams(flRoot,true)
+            peerFl?.let { AgoraManager.setupRemoteVideo(this@UserRoomActivity,peerAnchorId, it) }
+
+        }
+    }
+
+    override fun stopPK(stopPKModel: StopPKModel) {
+        setPKLayoutParams(flRoot,false)
+        AgoraManager.removeRemoteVideo(peerAnchorId,peerFl)
+    }
+
+    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
+        if (!isGetDataFromIM){
+            //如果是通过接口获取的
+            peerAnchorId = punishPKModel.oppositeUserId.toInt()
+            setPKLayoutParams(flRoot,true)
+            peerFl?.let { AgoraManager.setupRemoteVideo(this@UserRoomActivity,peerAnchorId, it) }
+        }
+    }
+
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
+
+    }
+
+    private val marginTopValue by lazy {
+        ImmersionBar.getStatusBarHeight(this) + DpPxUtil.dip2px(78f)
+    }
+
+    //设置视频画面大小
+    private fun setPKLayoutParams(view:View?,isPK:Boolean){
+        if (isPK){
+            val x = DpPxUtil.getScreenWidth() / 2
+            val y = DpPxUtil.getScreenWidth() * 275 / 360
+            val params = ConstraintLayout.LayoutParams(x, y)
+            params.topToTop = R.id.rootUserView
+            params.startToStart = R.id.rootUserView
+            params.width = x
+            params.height = y
+            params.topMargin = marginTopValue
+            view?.layoutParams = params
+        }else{
+            val params = ConstraintLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT
+            )
+            view?.layoutParams = params
+        }
+    }
+
+    private fun initPeerAnchorLayoutParams() {
+        val x = DpPxUtil.getScreenWidth() / 2
+        val y = DpPxUtil.getScreenWidth() * 275 / 360
+        val params = ConstraintLayout.LayoutParams(x, y)
+        params.topToTop = R.id.rootUserView
+        params.endToEnd = R.id.rootUserView
+        params.width = x
+        params.height = y
+        params.topMargin = marginTopValue
+        peerFl?.layoutParams = params
+    }
+
+
 }

+ 18 - 0
room/src/main/java/com/swago/room/user/UserRoomFragment.kt

@@ -9,6 +9,10 @@ import com.swago.baseswago.baseroom.IRoomInfo
 import com.swago.baseswago.baseroom.SwagoRoomManager
 import com.swago.baseswago.dialog.BenefitBagDialog
 import com.swago.baseswago.dialog.ReportDialog
+import com.swago.baseswago.model.live.pk.ProcessPKModel
+import com.swago.baseswago.model.live.pk.PunishPKModel
+import com.swago.baseswago.model.live.pk.StartPKModel
+import com.swago.baseswago.model.live.pk.StopPKModel
 import com.swago.baseswago.util.AppContext
 import com.swago.baseswago.util.NoDoubleClickListener
 import com.swago.baseswago.util.UserInfo
@@ -203,6 +207,20 @@ class UserRoomFragment : BaseComFragment<FragmentBaseComBinding>() {
         super.closeRoomed()
     }
 
+    /*********************PK**************************/
+    override fun startPK(startPKModel: StartPKModel, isGetDataFromIM: Boolean) {
+    }
+
+    override fun stopPK(stopPKModel: StopPKModel) {
+    }
+
+    override fun punishPK(punishPKModel: PunishPKModel, isGetDataFromIM: Boolean) {
+    }
+
+    override fun processChangePK(processPKModel: ProcessPKModel,isGetDataFromIM: Boolean) {
+    }
+    /*********************PK**************************/
+
     override val iHeader: IHeader by lazy {
         ComHeaderView(requireContext())
     }

+ 7 - 0
room/src/main/java/com/swago/room/widget/AnchorFooterView.kt

@@ -24,6 +24,7 @@ class AnchorFooterView : ConstraintLayout, IFooter, IRoomActiveListener {
     var openSendMsgDialog:(()->Unit)? = null
     var openMessageFun:(()->Unit)? = null
     var openGameFun:(()->Unit)? = null
+    var openPKFun:(()->Unit)? = null
 
     constructor(context: Context) : this(context, null)
     constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
@@ -61,6 +62,12 @@ class AnchorFooterView : ConstraintLayout, IFooter, IRoomActiveListener {
                 openGameFun?.invoke()
             }
         })
+
+        binding.ivPK.setOnClickListener(object : NoDoubleClickListener() {
+            override fun onClick() {
+                openPKFun?.invoke()
+            }
+        })
     }
 
     override fun getFooterView(): View {

+ 1 - 0
room/src/main/res/layout/activity_anchor_room.xml

@@ -3,6 +3,7 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:id="@+id/rootAnchorView"
+    android:background="@mipmap/bg_room"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <!--自己-->

+ 2 - 0
room/src/main/res/layout/dialog_pk_accept.xml

@@ -8,6 +8,8 @@
     <androidx.constraintlayout.widget.ConstraintLayout
         android:background="@drawable/shape_161722_top_20"
         app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:paddingBottom="10dp"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 

+ 12 - 9
room/src/main/res/layout/dialog_pk_invite.xml

@@ -8,6 +8,8 @@
     <androidx.constraintlayout.widget.ConstraintLayout
         android:background="@drawable/shape_161722_top_20"
         app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:paddingBottom="10dp"
         android:layout_width="match_parent"
         android:layout_height="wrap_content">
 
@@ -103,25 +105,26 @@
             android:textSize="16dp"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toTopOf="@+id/tvInvite"
+            app:layout_constraintTop_toBottomOf="@+id/tvSelfName"
+            android:layout_marginTop="12dp"
             android:text="@string/inviting_time"
             android:visibility="gone"
-            app:layout_constraintBottom_toBottomOf="@+id/tvInvite"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"/>
 
-
-        <com.swago.baseswago.cusview.MediumTextView
+        <com.swago.baseswago.cusview.BoldTextView
             android:id="@+id/tvCancel"
             android:textSize="16dp"
             android:textColor="#fff"
-            android:layout_marginTop="10dp"
+            android:layout_marginStart="15dp"
+            android:layout_marginEnd="15dp"
+            android:layout_marginTop="52dp"
             android:text="@string/cancel"
             android:gravity="center"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toBottomOf="@+id/tvInvite"
-            android:layout_width="wrap_content"
+            android:visibility="gone"
+            android:background="@drawable/shape_ff56b7_37"
+            app:layout_constraintTop_toBottomOf="@+id/tvSelfName"
+            android:layout_width="match_parent"
             android:layout_height="48dp"/>
 
     </androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 1
room/src/main/res/layout/dialog_pk_search.xml

@@ -52,7 +52,7 @@
             android:layout_height="wrap_content"/>
 
 
-        <androidx.recyclerview.widget.RecyclerView
+        <com.swago.baseswago.cusview.SwagoRecyclerView
             android:id="@+id/rvPKList"
             android:layout_marginTop="16dp"
             app:layout_constraintTop_toBottomOf="@+id/etEdit"

+ 0 - 3
room/src/main/res/layout/fragment_base_com.xml

@@ -20,7 +20,6 @@
         android:layout_marginBottom="10dp"
         app:layout_constraintBottom_toBottomOf="parent" />
 
-
     <com.swago.room.pk.PKLayoutView
         android:id="@+id/pkLayoutView"
         android:layout_marginTop="14dp"
@@ -29,7 +28,6 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"/>
 
-
     <com.swago.room.widget.ChatRecyclerView
         android:id="@+id/rv"
         android:layout_marginStart="10dp"
@@ -40,7 +38,6 @@
         android:layout_width="match_parent"
         android:layout_height="170dp"/>
 
-
     <com.swago.room.hongbao.RedEnvelopeView
         android:id="@+id/ivRedEnvelopeView"
         android:layout_marginBottom="120dp"

+ 2 - 1
room/src/main/res/layout/item_pk_search.xml

@@ -3,7 +3,6 @@
     android:layout_width="match_parent"
     android:layout_height="72dp"
     xmlns:tools="http://schemas.android.com/tools"
-    android:background="#000"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <de.hdodenhof.circleimageview.CircleImageView
@@ -32,6 +31,7 @@
         app:layout_constraintStart_toEndOf="@+id/tvName"
         app:layout_constraintTop_toTopOf="@+id/tvName"
         android:layout_marginTop="2dp"
+        android:layout_marginStart="6dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>
 
@@ -39,6 +39,7 @@
     <ImageView
         android:id="@+id/ivSex"
         tools:src="@mipmap/female"
+        android:layout_marginStart="5dp"
         app:layout_constraintStart_toEndOf="@+id/tvLevel"
         app:layout_constraintTop_toTopOf="@+id/tvLevel"
         app:layout_constraintBottom_toBottomOf="@+id/tvLevel"

+ 7 - 0
room/src/main/res/layout/item_pk_seat.xml

@@ -12,4 +12,11 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
 
+    <ImageView
+        android:id="@+id/ivPosition"
+        app:layout_constraintEnd_toEndOf="@+id/ivAvatar"
+        app:layout_constraintBottom_toBottomOf="parent"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 12 - 1
room/src/main/res/layout/layout_anchor_footer_view.xml

@@ -27,11 +27,22 @@
         android:layout_height="40dp"/>
 
     <ImageView
-        android:id="@+id/ivGame"
+        android:id="@+id/ivPK"
         android:layout_marginStart="10dp"
         android:background="@drawable/shape_80000000_20"
         app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toEndOf="@+id/ivSwitchCamera"
+        android:src="@mipmap/live_pk"
+        android:padding="7dp"
+        android:layout_width="40dp"
+        android:layout_height="40dp"/>
+
+    <ImageView
+        android:id="@+id/ivGame"
+        android:layout_marginStart="10dp"
+        android:background="@drawable/shape_80000000_20"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toEndOf="@+id/ivPK"
         android:src="@mipmap/live_game"
         android:visibility="gone"
         tools:visibility="visible"

+ 14 - 14
room/src/main/res/layout/layout_pk_view.xml

@@ -2,7 +2,6 @@
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="#000"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools">
 
@@ -27,7 +26,7 @@
 
     <ImageView
         android:id="@+id/ivPeerPKResult"
-        android:layout_marginStart="8dp"
+        android:layout_marginEnd="8dp"
         android:layout_marginTop="8dp"
         android:visibility="gone"
         tools:visibility="visible"
@@ -43,8 +42,8 @@
         app:layout_constraintBottom_toBottomOf="@+id/view"
         android:id="@+id/svgPKResult"
         android:visibility="gone"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"/>
+        android:layout_width="320dp"
+        android:layout_height="192dp"/>
 
     <androidx.constraintlayout.widget.ConstraintLayout
         android:id="@+id/clPeer"
@@ -109,20 +108,14 @@
         android:progressDrawable="@drawable/pk_progress_style"
        app:layout_constraintTop_toBottomOf="@+id/view"/>
 
-    <com.opensource.svgaplayer.SVGAImageView
-        app:layout_constraintStart_toStartOf="@+id/progressBar"
-        app:layout_constraintTop_toTopOf="@+id/progressBar"
-        android:id="@+id/svgProgress"
-        android:layout_width="wrap_content"
-        android:layout_height="15dp"/>
-
     <TextView
         android:id="@+id/tvSelf"
-        tools:text="213"
+        android:text="0"
         android:textSize="12dp"
         android:textColor="#fff"
         android:gravity="center_vertical"
         app:layout_constraintTop_toTopOf="@+id/progressBar"
+        app:layout_constraintBottom_toBottomOf="@+id/progressBar"
         app:layout_constraintStart_toStartOf="parent"
         android:drawableStart="@mipmap/icon_coin_pk"
         android:layout_width="wrap_content"
@@ -131,17 +124,24 @@
 
     <TextView
         android:id="@+id/tvPeer"
-        tools:text="213"
+        android:text="0"
         android:textSize="12dp"
         android:textColor="#fff"
         android:gravity="center_vertical"
+        app:layout_constraintBottom_toBottomOf="@+id/progressBar"
         app:layout_constraintTop_toTopOf="@+id/progressBar"
         app:layout_constraintEnd_toEndOf="parent"
         android:drawableEnd="@mipmap/icon_coin_pk"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"/>
 
-
+    <com.opensource.svgaplayer.SVGAImageView
+        app:layout_constraintStart_toStartOf="@+id/progressBar"
+        app:layout_constraintTop_toBottomOf="@+id/view"
+        android:layout_marginTop="-3dp"
+        android:id="@+id/svgProgress"
+        android:layout_width="20dp"
+        android:layout_height="wrap_content"/>
 
     <androidx.recyclerview.widget.RecyclerView
         android:id="@+id/rvSelf"

+ 8 - 0
room/src/main/res/layout/layout_user_room.xml

@@ -4,6 +4,7 @@
     android:layout_height="match_parent"
     xmlns:tools="http://schemas.android.com/tools"
     tools:viewBindingIgnore="true"
+    android:id="@+id/rootUserView"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <FrameLayout
@@ -11,6 +12,13 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"/>
 
+    <FrameLayout
+        android:id="@+id/peerFl"
+        android:layoutDirection="ltr"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+    </FrameLayout>
+
     <androidx.viewpager.widget.ViewPager
         android:id="@+id/viewPager"
         android:layout_width="match_parent"

BIN
room/src/main/res/mipmap-xxhdpi/bg_room.webp


BIN
room/src/main/res/mipmap-xxhdpi/first.png


BIN
room/src/main/res/mipmap-xxhdpi/live_pk.webp


BIN
room/src/main/res/mipmap-xxhdpi/second.png


BIN
room/src/main/res/mipmap-xxhdpi/third.png


+ 2 - 3
user/src/main/java/com/swago/user/adapter/BlackListAdapter.kt

@@ -4,6 +4,7 @@ import com.bumptech.glide.Glide
 import com.chad.library.adapter.base.BaseQuickAdapter
 import com.chad.library.adapter.base.BaseViewHolder
 import com.swago.baseswago.model.BlackListModel
+import com.swago.loadUrl
 import com.swago.user.R
 import de.hdodenhof.circleimageview.CircleImageView
 
@@ -24,9 +25,7 @@ class BlackListAdapter: BaseQuickAdapter<BlackListModel.ListBean, BaseViewHolder
             }
 
             val ivAvatar = itemView.findViewById<CircleImageView>(R.id.ivAvatar)
-            Glide.with(itemView.context).load(item.user_head_img_url)
-                .placeholder(R.mipmap.default_avatar)
-                .error(R.mipmap.default_avatar).into(ivAvatar)
+            ivAvatar.loadUrl(itemView.context,item.user_head_img_url)
             addOnClickListener(R.id.ivStatus)
         }