From 3d15c5563c87eab5ce5931d73dc872da4e4fb9b7 Mon Sep 17 00:00:00 2001 From: abyyxwang Date: Thu, 18 Mar 2021 14:31:03 +0800 Subject: [PATCH] =?UTF-8?q?iOS=20=E6=9B=B4=E6=96=B08.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Demo/ReplaykitUpload/Info.plist | 4 +- Demo/ReplaykitUpload/TRTCInfo.plist | 4 +- Demo/TXLiteAVDemo.xcodeproj/project.pbxproj | 514 +++++-- Demo/TXLiteAVDemo/App/Info.plist | 4 +- .../App/Main/MainViewController.m | 2 + .../Assets.xcassets/Main/Contents.json | 6 +- .../TXLiteAVDemo/App/TRTC-Appstore-Info.plist | 4 +- .../App/TXLiteAVDemo-Bridging-Header.h | 5 + .../project.pbxproj | 8 +- .../V2PlayerViewController.m | 79 +- .../V2PusherViewController.m | 34 +- .../V2Setting/V2PlayerSettingViewController.m | 27 +- .../V2Setting/V2PusherSettingViewController.m | 37 +- .../V2SettingModel/V2PusherSettingModel.h | 2 +- .../V2SettingModel/V2PusherSettingModel.m | 32 +- .../LiveRoomUI/LiveRoomPusherViewController.m | 5 + .../model/Impl/TRTCChatSalon.m | 1197 +++++++++++++++++ .../model/Impl/TRTCChatSalonDef.m | 63 + .../model/Impl/base/TXChatSalonBaseDef.h | 69 + .../model/Impl/base/TXChatSalonBaseDef.m | 37 + .../model/Impl/base/TXChatSalonCommonDef.h | 55 + .../Impl/chatsalon/TXChatSalonIMJsonHandle.h | 58 + .../Impl/chatsalon/TXChatSalonIMJsonHandle.m | 101 ++ .../model/Impl/chatsalon/TXChatSalonService.h | 96 ++ .../model/Impl/chatsalon/TXChatSalonService.m | 980 ++++++++++++++ .../model/Impl/trtc/ChatSalonTRTCService.h | 72 + .../model/Impl/trtc/ChatSalonTRTCService.m | 236 ++++ .../TRTCChatSalonDemo/model/TRTCChatSalon.h | 305 +++++ .../model/TRTCChatSalonDef.h | 68 + .../model/TRTCChatSalonDelegate.h | 140 ++ .../TRTCChatSalonManager.swift | 112 ++ .../AppIcon.appiconset/Contents.json | 98 ++ .../Contents.json | 6 + .../chat_salon/Contents.json | 6 + .../navigationbar_back.imageset/Contents.json | 23 + .../navigationbar_back.png | Bin 0 -> 290 bytes .../navigationbar_back@2x.png | Bin 0 -> 550 bytes .../navigationbar_back@3x.png | Bin 0 -> 985 bytes .../Contents.json | 23 + .../voiceroom_audioEffect_close.png | Bin 0 -> 1095 bytes .../voiceroom_audioEffect_close@2x.png | Bin 0 -> 2569 bytes .../voiceroom_audioEffect_close@3x.png | Bin 0 -> 4101 bytes .../Contents.json | 23 + .../voiceroom_audioEffect_open.png | Bin 0 -> 1036 bytes .../voiceroom_audioEffect_open@2x.png | Bin 0 -> 2460 bytes .../voiceroom_audioEffect_open@3x.png | Bin 0 -> 4021 bytes .../voiceroom_cover1.imageset/Contents.json | 21 + .../voiceroom_cover1.imageset/avatar0_100.png | Bin 0 -> 62337 bytes .../voiceroom_cover2.imageset/Contents.json | 21 + .../voiceroom_cover2.imageset/avatar1_100.png | Bin 0 -> 86050 bytes .../voiceroom_cover3.imageset/Contents.json | 21 + .../voiceroom_cover3.imageset/avatar2_100.png | Bin 0 -> 86943 bytes .../Contents.json | 23 + .../voiceroom_create_room.png | Bin 0 -> 2006 bytes .../voiceroom_create_room@2x.png | Bin 0 -> 4425 bytes .../voiceroom_create_room@3x.png | Bin 0 -> 7194 bytes .../Contents.json | 23 + .../voiceroom_like_normal.png | Bin 0 -> 863 bytes .../voiceroom_like_normal@2x.png | Bin 0 -> 1786 bytes .../voiceroom_like_normal@3x.png | Bin 0 -> 2644 bytes .../Contents.json | 23 + .../voiceroom_like_selected.png | Bin 0 -> 850 bytes .../voiceroom_like_selected@2x.png | Bin 0 -> 1731 bytes .../voiceroom_like_selected@3x.png | Bin 0 -> 2564 bytes .../Contents.json | 23 + .../voiceroom_message_normal.png | Bin 0 -> 1044 bytes .../voiceroom_message_normal@2x.png | Bin 0 -> 2149 bytes .../voiceroom_message_normal@3x.png | Bin 0 -> 3510 bytes .../Contents.json | 23 + .../voiceroom_message_select.png | Bin 0 -> 1023 bytes .../voiceroom_message_select@2x.png | Bin 0 -> 2120 bytes .../voiceroom_message_select@3x.png | Bin 0 -> 3438 bytes .../Contents.json | 23 + .../voiceroom_mic_close.png | Bin 0 -> 1051 bytes .../voiceroom_mic_close@2x.png | Bin 0 -> 2145 bytes .../voiceroom_mic_close@3x.png | Bin 0 -> 3423 bytes .../voiceroom_mic_dis.imageset/Contents.json | 21 + .../voiceroom_mic_dis.png | Bin 0 -> 932 bytes .../voiceroom_mic_open.imageset/Contents.json | 23 + .../voiceroom_mic_open.png | Bin 0 -> 801 bytes .../voiceroom_mic_open@2x.png | Bin 0 -> 1695 bytes .../voiceroom_mic_open@3x.png | Bin 0 -> 2727 bytes .../voiceroom_oval.imageset/Contents.json | 23 + .../voiceroom_oval.png | Bin 0 -> 590 bytes .../voiceroom_oval@2x.png | Bin 0 -> 1256 bytes .../voiceroom_oval@3x.png | Bin 0 -> 1899 bytes .../Contents.json | 23 + .../voiceroom_placeholder_avatar.png | Bin 0 -> 3818 bytes .../voiceroom_placeholder_avatar@2x.png | Bin 0 -> 8604 bytes .../voiceroom_placeholder_avatar@3x.png | Bin 0 -> 13676 bytes .../Contents.json | 23 + .../voiceroom_seat_lock.png | Bin 0 -> 2287 bytes .../voiceroom_seat_lock@2x.png | Bin 0 -> 4958 bytes .../voiceroom_seat_lock@3x.png | Bin 0 -> 7903 bytes .../voiceroom_selected.imageset/Contents.json | 23 + .../voiceroom_selected.png | Bin 0 -> 562 bytes .../voiceroom_selected@2x.png | Bin 0 -> 1041 bytes .../voiceroom_selected@3x.png | Bin 0 -> 1457 bytes .../Contents.json | 23 + .../voiceroom_voice_close.png | Bin 0 -> 1041 bytes .../voiceroom_voice_close@2x.png | Bin 0 -> 2288 bytes .../voiceroom_voice_close@3x.png | Bin 0 -> 3559 bytes .../Contents.json | 23 + .../voiceroom_voice_open.png | Bin 0 -> 1058 bytes .../voiceroom_voice_open@2x.png | Bin 0 -> 2313 bytes .../voiceroom_voice_open@3x.png | Bin 0 -> 3614 bytes .../chatsalon_add_mic.imageset/Contents.json | 22 + .../chatsalon_add_mic.png | Bin 0 -> 2259 bytes .../chatsalon_add_mic@2x.png | Bin 0 -> 2285 bytes .../Contents.json | 22 + .../chatsalon_added_mic.png | Bin 0 -> 815 bytes .../chatsalon_added_mic@2x.png | Bin 0 -> 1481 bytes .../chatsalon_anchor.imageset/Contents.json | 22 + .../chatsalon_anchor@1x.png | Bin 0 -> 398 bytes .../chatsalon_anchor@2x.png | Bin 0 -> 744 bytes .../chatsalon_audience.imageset/Contents.json | 22 + .../chatsalon_audience@1x.png | Bin 0 -> 409 bytes .../chatsalon_audience@2x.png | Bin 0 -> 664 bytes .../chatsalon_handsup.imageset/Contents.json | 22 + .../chatsalon_handsup@1x.png | Bin 0 -> 1412 bytes .../chatsalon_handsup@2x.png | Bin 0 -> 3030 bytes .../Contents.json | 22 + .../chatsalon_handsup_cancel@1x.png | Bin 0 -> 1468 bytes .../chatsalon_handsup_cancel@2x.png | Bin 0 -> 3229 bytes .../Contents.json | 22 + .../chatsalon_handsup_list@1x.png | Bin 0 -> 1466 bytes .../chatsalon_handsup_list@2x.png | Bin 0 -> 3234 bytes .../Contents.json | 22 + .../chatsalon_handsup_success.png | Bin 0 -> 368 bytes .../chatsalon_handsup_success@2x.png | Bin 0 -> 598 bytes .../Contents.json | 22 + .../chatsalon_leave_mic@1x.png | Bin 0 -> 1903 bytes .../chatsalon_leave_mic@2x.png | Bin 0 -> 4169 bytes .../chatsalon_loading.imageset/Contents.json | 22 + .../chatsalon_loading@1x.png | Bin 0 -> 1090 bytes .../chatsalon_loading@2x.png | Bin 0 -> 2834 bytes .../chatsalon_master.imageset/Contents.json | 22 + .../chatsalon_master@1x.png | Bin 0 -> 515 bytes .../chatsalon_master@2x.png | Bin 0 -> 1068 bytes .../chatsalon_mic_mute.imageset/Contents.json | 22 + .../chatsalon_mic_mute@1x.png | Bin 0 -> 817 bytes .../chatsalon_mic_mute@2x.png | Bin 0 -> 1720 bytes .../chatsalon_mic_off.imageset/Contents.json | 22 + .../chatsalon_mic_off@1x.png | Bin 0 -> 1910 bytes .../chatsalon_mic_off@2x.png | Bin 0 -> 4061 bytes .../chatsalon_mic_on.imageset/Contents.json | 22 + .../chatsalon_mic_on@1x.png | Bin 0 -> 1667 bytes .../chatsalon_mic_on@2x.png | Bin 0 -> 3461 bytes .../transparent.imageset/Contents.json | 21 + .../transparent.imageset/transparent.png | Bin 0 -> 824 bytes .../ui/TRTCChatSalonEnteryControl.swift | 116 ++ .../SubViews/TRTCChatSalonListCell.swift | 103 ++ .../TRTCChatSalonListRootView.swift | 202 +++ .../TRTCChatSalonListViewController.swift | 79 ++ .../TRTCChatSalonListViewModel.swift | 125 ++ .../ui/TRTCChatSalonLocalized.swift | 32 + .../SubViews/TRTCCSAudienceListView.swift | 154 +++ .../TRTCCSAudienceTableViewCell.swift | 121 ++ .../TRTCChatSalonHandsUpTipsView.swift | 71 + .../SubViews/TRTCChatSalonMainMenuView.swift | 150 +++ .../SubViews/TRTCChatSalonSeatCell.swift | 49 + .../SubViews/TRTCChatSalonSeatView.swift | 222 +++ .../TRTCChatSalonTakeSeatTipsView.swift | 126 ++ .../SubViews/TRTCChatSalonTipsTableCell.swift | 145 ++ .../SubViews/TRTCChatSalonTipsView.swift | 118 ++ .../TRTCChatSalonRootView.swift | 675 ++++++++++ .../TRTCChatSalonVIewDataDef.swift | 76 ++ .../TRTCChatSalonViewController.swift | 104 ++ .../TRTCChatSalonViewModel.swift | 799 +++++++++++ .../TRTCCreateChatSalonRootView.swift | 290 ++++ .../TRTCCreateChatSalonViewController.swift | 47 + .../TRTCCreateChatSalonViewModel.swift | 76 ++ .../TRTCChatSalonDemoLocalized.strings | 66 + .../TRTCChatSalonDemoLocalized.strings | 66 + .../ui/Anchor/TCAnchorToolbarView.m | 10 +- .../TRTCVoiceRoomViewModel.swift | 4 +- .../UGCKit/UGCKit.xcodeproj/project.pbxproj | 8 +- .../VideoUpload/TVCClientInner.h | 2 +- 178 files changed, 9066 insertions(+), 217 deletions(-) create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalon.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalonDef.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonCommonDef.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.m create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalon.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDef.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDelegate.h create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/NetworkRoomManager/TRTCChatSalonManager.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/navigationbar_back.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/navigationbar_back@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/navigationbar_back@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_open.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_open.imageset/voiceroom_audioEffect_open.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_open.imageset/voiceroom_audioEffect_open@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_open.imageset/voiceroom_audioEffect_open@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover1.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover1.imageset/avatar0_100.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover2.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover2.imageset/avatar1_100.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/avatar2_100.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_create_room.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_create_room.imageset/voiceroom_create_room.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_create_room.imageset/voiceroom_create_room@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_create_room.imageset/voiceroom_create_room@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/voiceroom_like_selected.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/voiceroom_like_selected@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/voiceroom_like_selected@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_normal.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_normal.imageset/voiceroom_message_normal.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_normal.imageset/voiceroom_message_normal@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_normal.imageset/voiceroom_message_normal@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/voiceroom_message_select.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/voiceroom_message_select@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/voiceroom_message_select@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/voiceroom_mic_close.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/voiceroom_mic_close@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/voiceroom_mic_close@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_dis.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_dis.imageset/voiceroom_mic_dis.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_open.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_open.imageset/voiceroom_mic_open.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_open.imageset/voiceroom_mic_open@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_open.imageset/voiceroom_mic_open@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/voiceroom_oval.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/voiceroom_oval@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/voiceroom_oval@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/voiceroom_placeholder_avatar.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/voiceroom_placeholder_avatar@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/voiceroom_placeholder_avatar@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_seat_lock.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_seat_lock.imageset/voiceroom_seat_lock.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_seat_lock.imageset/voiceroom_seat_lock@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_seat_lock.imageset/voiceroom_seat_lock@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/voiceroom_voice_open.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/voiceroom_voice_open@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/voiceroom_voice_open@3x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_added_mic.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_added_mic.imageset/chatsalon_added_mic.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_added_mic.imageset/chatsalon_added_mic@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_audience.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_audience.imageset/chatsalon_audience@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_audience.imageset/chatsalon_audience@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/chatsalon_handsup@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/chatsalon_handsup@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_cancel.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_cancel.imageset/chatsalon_handsup_cancel@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_cancel.imageset/chatsalon_handsup_cancel@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_list.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_list.imageset/chatsalon_handsup_list@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_list.imageset/chatsalon_handsup_list@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/chatsalon_handsup_success.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/chatsalon_handsup_success@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/chatsalon_loading@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/chatsalon_loading@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_mute.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_mute.imageset/chatsalon_mic_mute@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_mute.imageset/chatsalon_mic_mute@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_off.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_off.imageset/chatsalon_mic_off@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_off.imageset/chatsalon_mic_off@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_on.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_on.imageset/chatsalon_mic_on@1x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_on.imageset/chatsalon_mic_on@2x.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/transparent.imageset/Contents.json create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/transparent.imageset/transparent.png create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonEnteryControl.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/SubViews/TRTCChatSalonListCell.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListRootView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewController.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewModel.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonLocalized.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceListView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceTableViewCell.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonHandsUpTipsView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonMainMenuView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatCell.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTakeSeatTipsView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsTableCell.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonRootView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonVIewDataDef.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewController.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewModel.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonRootView.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewController.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewModel.swift create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/en.lproj/TRTCChatSalonDemoLocalized.strings create mode 100644 Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/zh-Hans.lproj/TRTCChatSalonDemoLocalized.strings diff --git a/Demo/ReplaykitUpload/Info.plist b/Demo/ReplaykitUpload/Info.plist index 51ba4f2d..6b2bd168 100644 --- a/Demo/ReplaykitUpload/Info.plist +++ b/Demo/ReplaykitUpload/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 8.4.672 + 8.5.670 CFBundleVersion - 672 + 670 NSExtension NSExtensionPointIdentifier diff --git a/Demo/ReplaykitUpload/TRTCInfo.plist b/Demo/ReplaykitUpload/TRTCInfo.plist index 3c574990..d2408be4 100644 --- a/Demo/ReplaykitUpload/TRTCInfo.plist +++ b/Demo/ReplaykitUpload/TRTCInfo.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 8.4.672 + 8.5.670 CFBundleVersion - 672 + 670 NSExtension NSExtensionPointIdentifier diff --git a/Demo/TXLiteAVDemo.xcodeproj/project.pbxproj b/Demo/TXLiteAVDemo.xcodeproj/project.pbxproj index d30082bb..bfc4f014 100644 --- a/Demo/TXLiteAVDemo.xcodeproj/project.pbxproj +++ b/Demo/TXLiteAVDemo.xcodeproj/project.pbxproj @@ -7,15 +7,20 @@ objects = { /* Begin PBXBuildFile section */ - 177CC32C2A559AF6A5193DF1 /* LoginViewController+UI_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C05FC57FE01B46C47BAB4724 /* LoginViewController+UI_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 16C9F6315A0B86B5186D8070 /* ProfileManager_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FF8387DBA07E8B109025674 /* ProfileManager_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 1A3781E466CB5454F31BF136 /* LoginViewController+UI_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBBD9C13D61DA96FDFBCEA2 /* LoginViewController+UI_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 1DC7F349A2B6380DCA056281 /* libPods-TXReplaykitUpload_Professional.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00809C5850F41459EC8EE3D8 /* libPods-TXReplaykitUpload_Professional.a */; }; 1EA0A986FB03B486F983DE95 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; + 2366FA9BBE88A1C08D73AF1E /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC01445D40A66EAACDE64424 /* ProfileViewController.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 2840D91C24B8562200723FBC /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2840D91B24B8562200723FBC /* AudioToolbox.framework */; }; 2840D92924B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2840D92824B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift */; }; 2840D92A24B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2840D92824B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift */; }; 2840D92E24B8801800723FBC /* SDWebImagePlaceholderImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2840D92824B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift */; }; 2840D93124B880EF00723FBC /* SDWebImagePlaceholderImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2840D92824B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift */; }; 285FB46824BEA52F00FFB2BC /* TXVoiceRoomService.m in Sources */ = {isa = PBXBuildFile; fileRef = 4046B13924B36AD700F27349 /* TXVoiceRoomService.m */; }; + 2D14F385032F832FF7E38644 /* AppUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB08160F5F234CE7746B24A2 /* AppUtils.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 338E38575707B25D2EC253D6 /* ProfileViewController+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CE9060FD1C67F1E97A6A8B2 /* ProfileViewController+UI.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 3B62B23CE22937D37BE1E8B9 /* LoginViewController_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05725444B653F4415E5FB879 /* LoginViewController_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 40091E661F4FCBB9009B882D /* UIButton+Glossy.m in Sources */ = {isa = PBXBuildFile; fileRef = 40F8534B1EE8FCDF00EE47D7 /* UIButton+Glossy.m */; }; 40091E6B1F4FCBB9009B882D /* ScanQRController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40F853561EE8FCDF00EE47D7 /* ScanQRController.mm */; }; 40091E6F1F4FCBB9009B882D /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 40F853261EE8FC8400EE47D7 /* AppDelegate.m */; }; @@ -179,6 +184,30 @@ 4011CC4424E4DDB600C543D7 /* TRTCCalling+Signal.m in Sources */ = {isa = PBXBuildFile; fileRef = 4011CC1C24E4DDB600C543D7 /* TRTCCalling+Signal.m */; }; 4011CC4524E4DDB600C543D7 /* TRTCCalling+Signal.m in Sources */ = {isa = PBXBuildFile; fileRef = 4011CC1C24E4DDB600C543D7 /* TRTCCalling+Signal.m */; }; 4011CC4624E4DDB600C543D7 /* TRTCCalling+Signal.m in Sources */ = {isa = PBXBuildFile; fileRef = 4011CC1C24E4DDB600C543D7 /* TRTCCalling+Signal.m */; }; + 4024558E25FF9A0700267B13 /* v1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558225FF9A0500267B13 /* v1 */; }; + 4024558F25FF9A0700267B13 /* v1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558225FF9A0500267B13 /* v1 */; }; + 4024559025FF9A0700267B13 /* YTHandDetector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558325FF9A0600267B13 /* YTHandDetector.bundle */; }; + 4024559125FF9A0700267B13 /* YTHandDetector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558325FF9A0600267B13 /* YTHandDetector.bundle */; }; + 4024559225FF9A0700267B13 /* e1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558425FF9A0600267B13 /* e1 */; }; + 4024559325FF9A0700267B13 /* e1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558425FF9A0600267B13 /* e1 */; }; + 4024559425FF9A0700267B13 /* poseest.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558525FF9A0600267B13 /* poseest.bundle */; }; + 4024559525FF9A0700267B13 /* poseest.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558525FF9A0600267B13 /* poseest.bundle */; }; + 4024559625FF9A0700267B13 /* o1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558625FF9A0600267B13 /* o1 */; }; + 4024559725FF9A0700267B13 /* o1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558625FF9A0600267B13 /* o1 */; }; + 4024559825FF9A0700267B13 /* AECore.metallib in Resources */ = {isa = PBXBuildFile; fileRef = 4024558725FF9A0600267B13 /* AECore.metallib */; }; + 4024559925FF9A0700267B13 /* AECore.metallib in Resources */ = {isa = PBXBuildFile; fileRef = 4024558725FF9A0600267B13 /* AECore.metallib */; }; + 4024559A25FF9A0700267B13 /* MSFMLandmarks46_relandmark_models.xbin in Resources */ = {isa = PBXBuildFile; fileRef = 4024558825FF9A0600267B13 /* MSFMLandmarks46_relandmark_models.xbin */; }; + 4024559B25FF9A0700267B13 /* MSFMLandmarks46_relandmark_models.xbin in Resources */ = {isa = PBXBuildFile; fileRef = 4024558825FF9A0600267B13 /* MSFMLandmarks46_relandmark_models.xbin */; }; + 4024559C25FF9A0700267B13 /* FilterEngine.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558925FF9A0600267B13 /* FilterEngine.bundle */; }; + 4024559D25FF9A0700267B13 /* FilterEngine.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558925FF9A0600267B13 /* FilterEngine.bundle */; }; + 4024559E25FF9A0700267B13 /* RPNSegmenter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558A25FF9A0600267B13 /* RPNSegmenter.bundle */; }; + 4024559F25FF9A0700267B13 /* RPNSegmenter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558A25FF9A0600267B13 /* RPNSegmenter.bundle */; }; + 402455A025FF9A0700267B13 /* u1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558B25FF9A0600267B13 /* u1 */; }; + 402455A125FF9A0700267B13 /* u1 in Resources */ = {isa = PBXBuildFile; fileRef = 4024558B25FF9A0600267B13 /* u1 */; }; + 402455A225FF9A0700267B13 /* ufa.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558C25FF9A0700267B13 /* ufa.bundle */; }; + 402455A325FF9A0700267B13 /* ufa.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558C25FF9A0700267B13 /* ufa.bundle */; }; + 402455A425FF9A0700267B13 /* detector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558D25FF9A0700267B13 /* detector.bundle */; }; + 402455A525FF9A0700267B13 /* detector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4024558D25FF9A0700267B13 /* detector.bundle */; }; 4028E6342456DC5B0000E428 /* QCloudCOSXML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0B8FBFF207E235A008D7982 /* QCloudCOSXML.framework */; }; 4028E6352456DC5F0000E428 /* QCloudCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A0B8FC00207E235B008D7982 /* QCloudCore.framework */; }; 402A00EE24506B7C0037A219 /* UGCRecordWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 402A00ED24506B7C0037A219 /* UGCRecordWrapper.m */; }; @@ -360,17 +389,6 @@ 4074E62D249F0F3A006C591F /* BuildFile in Embed App Extensions */ = {isa = PBXBuildFile; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 4074E64D249F1FCF006C591F /* AudioEffectSettingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40B5C6832484BBE500D3A718 /* AudioEffectSettingKit.framework */; }; 4074E64E249F1FD5006C591F /* AudioEffectSettingKitResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 40B5C6872484BBE500D3A718 /* AudioEffectSettingKitResources.bundle */; }; - 40802A1B24849EAA008151C1 /* AECore.metallib in Resources */ = {isa = PBXBuildFile; fileRef = 455DA212235566F400A5B146 /* AECore.metallib */; }; - 40802A1C24849EAE008151C1 /* detector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA215235566F500A5B146 /* detector.bundle */; }; - 40802A1D24849EB1008151C1 /* e1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21B235566F500A5B146 /* e1 */; }; - 40802A1E24849EB5008151C1 /* FilterEngine.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA214235566F500A5B146 /* FilterEngine.bundle */; }; - 40802A1F24849EB9008151C1 /* o1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21A235566F500A5B146 /* o1 */; }; - 40802A2024849EBD008151C1 /* poseest.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA213235566F400A5B146 /* poseest.bundle */; }; - 40802A2124849EBF008151C1 /* RPNSegmenter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA211235566F400A5B146 /* RPNSegmenter.bundle */; }; - 40802A2224849EC3008151C1 /* u1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA219235566F500A5B146 /* u1 */; }; - 40802A2324849EC6008151C1 /* ufa.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA216235566F500A5B146 /* ufa.bundle */; }; - 40802A2424849EFC008151C1 /* v1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA218235566F500A5B146 /* v1 */; }; - 40802A2524849EFF008151C1 /* YTHandDetector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA217235566F500A5B146 /* YTHandDetector.bundle */; }; 40802A2624849F02008151C1 /* YTFaceSDK.licence in Resources */ = {isa = PBXBuildFile; fileRef = CF61F5551FD690FB007CDAF4 /* YTFaceSDK.licence */; }; 40802A282484BBBE008151C1 /* AudioEffectSettingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40802A272484BBBE008151C1 /* AudioEffectSettingKit.framework */; }; 4088EB4F24599236005BF1DD /* TCBeautyPanel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40AA536524458EC800303EF7 /* TCBeautyPanel.framework */; }; @@ -561,18 +579,15 @@ 40B5C6942484BE4800D3A718 /* AudioEffectSettingKitResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 40B5C6872484BBE500D3A718 /* AudioEffectSettingKitResources.bundle */; }; 40B5C6952484BE5100D3A718 /* AudioEffectSettingKitResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 40B5C6872484BBE500D3A718 /* AudioEffectSettingKitResources.bundle */; }; 40B5C6962484BE5700D3A718 /* AudioEffectSettingKitResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 40B5C6872484BBE500D3A718 /* AudioEffectSettingKitResources.bundle */; }; - 40B5C6972484BE7500D3A718 /* AECore.metallib in Resources */ = {isa = PBXBuildFile; fileRef = 455DA212235566F400A5B146 /* AECore.metallib */; }; - 40B5C6982484BE7900D3A718 /* detector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA215235566F500A5B146 /* detector.bundle */; }; - 40B5C6992484BE7C00D3A718 /* e1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21B235566F500A5B146 /* e1 */; }; - 40B5C69A2484BE8000D3A718 /* FilterEngine.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA214235566F500A5B146 /* FilterEngine.bundle */; }; - 40B5C69B2484BE8300D3A718 /* o1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21A235566F500A5B146 /* o1 */; }; - 40B5C69C2484BE8600D3A718 /* poseest.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA213235566F400A5B146 /* poseest.bundle */; }; - 40B5C69D2484BE8A00D3A718 /* RPNSegmenter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA211235566F400A5B146 /* RPNSegmenter.bundle */; }; - 40B5C69E2484BE9200D3A718 /* u1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA219235566F500A5B146 /* u1 */; }; - 40B5C69F2484BE9500D3A718 /* ufa.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA216235566F500A5B146 /* ufa.bundle */; }; - 40B5C6A02484BE9900D3A718 /* v1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA218235566F500A5B146 /* v1 */; }; - 40B5C6A12484BE9C00D3A718 /* YTHandDetector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA217235566F500A5B146 /* YTHandDetector.bundle */; }; 40B5C6A22484BE9F00D3A718 /* YTFaceSDK.licence in Resources */ = {isa = PBXBuildFile; fileRef = CF61F5551FD690FB007CDAF4 /* YTFaceSDK.licence */; }; + 40BE0EE925EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */; }; + 40BE0EEA25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */; }; + 40BE0EEB25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */; }; + 40BE0EEC25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */; }; + 40BE0EF825EF762F00C58D6C /* TRTCChatSalonLocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */; }; + 40BE0EF925EF762F00C58D6C /* TRTCChatSalonLocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */; }; + 40BE0EFA25EF762F00C58D6C /* TRTCChatSalonLocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */; }; + 40BE0EFB25EF762F00C58D6C /* TRTCChatSalonLocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */; }; 40BEFEB6246942E400F4E10D /* TCBeautyPanelResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 40AA536724458EC800303EF7 /* TCBeautyPanelResources.bundle */; }; 40C0BD51244848D300931313 /* GenerateTestUserSig.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B3F8DC2446E6C5000C37A3 /* GenerateTestUserSig.m */; }; 40C0BD6B24484A1700931313 /* LiveRoomMainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B3F9272446E6C6000C37A3 /* LiveRoomMainViewController.swift */; }; @@ -621,6 +636,10 @@ 40C0BDE3244853FF00931313 /* TCAudienceViewController+LiveDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B3F9492446E6C6000C37A3 /* TCAudienceViewController+LiveDelegate.swift */; }; 40C0BDE4244853FF00931313 /* TCAudienceToolbarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B3F94A2446E6C6000C37A3 /* TCAudienceToolbarView.m */; }; 40C0BDE5244853FF00931313 /* LiveRoomMainViewController+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40B3F94C2446E6C6000C37A3 /* LiveRoomMainViewController+UI.swift */; }; + 40E18DA725ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */; }; + 40E18DA825ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */; }; + 40E18DA925ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */; }; + 40E18DAA25ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */; }; 40E1F43E2468F72900F3D350 /* UIColor+MLPFlatColors.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B3FA002447056D000C37A3 /* UIColor+MLPFlatColors.m */; }; 40E1F43F2468F72900F3D350 /* UIColor+MLPFlatColors.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B3FA002447056D000C37A3 /* UIColor+MLPFlatColors.m */; }; 40E1F4402468F72A00F3D350 /* UIColor+MLPFlatColors.m in Sources */ = {isa = PBXBuildFile; fileRef = 40B3FA002447056D000C37A3 /* UIColor+MLPFlatColors.m */; }; @@ -639,6 +658,114 @@ 40E25FCE2480C797005EB543 /* Portal+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E25FCC2480C796005EB543 /* Portal+Swift.swift */; }; 40E25FCF2480C797005EB543 /* Portal+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40E25FCC2480C796005EB543 /* Portal+Swift.swift */; }; 40E8146424A0F905007C4113 /* TRTCMeetingMoreViewShareVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AAEC25B2497807100B57D86 /* TRTCMeetingMoreViewShareVC.swift */; }; + 40EC852025E77AA500149FAA /* TRTCChatSalonDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */; }; + 40EC852125E77AA500149FAA /* TRTCChatSalonDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */; }; + 40EC852225E77AA500149FAA /* TRTCChatSalonDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */; }; + 40EC852325E77AA500149FAA /* TRTCChatSalonDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */; }; + 40EC852425E77AA500149FAA /* ChatSalonTRTCService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */; }; + 40EC852525E77AA500149FAA /* ChatSalonTRTCService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */; }; + 40EC852625E77AA500149FAA /* ChatSalonTRTCService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */; }; + 40EC852725E77AA500149FAA /* ChatSalonTRTCService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */; }; + 40EC852825E77AA500149FAA /* TXChatSalonService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851325E77AA500149FAA /* TXChatSalonService.m */; }; + 40EC852925E77AA500149FAA /* TXChatSalonService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851325E77AA500149FAA /* TXChatSalonService.m */; }; + 40EC852A25E77AA500149FAA /* TXChatSalonService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851325E77AA500149FAA /* TXChatSalonService.m */; }; + 40EC852B25E77AA500149FAA /* TXChatSalonService.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851325E77AA500149FAA /* TXChatSalonService.m */; }; + 40EC852C25E77AA500149FAA /* TXChatSalonIMJsonHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */; }; + 40EC852D25E77AA500149FAA /* TXChatSalonIMJsonHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */; }; + 40EC852E25E77AA500149FAA /* TXChatSalonIMJsonHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */; }; + 40EC852F25E77AA500149FAA /* TXChatSalonIMJsonHandle.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */; }; + 40EC853025E77AA500149FAA /* TRTCChatSalon.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851725E77AA500149FAA /* TRTCChatSalon.m */; }; + 40EC853125E77AA500149FAA /* TRTCChatSalon.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851725E77AA500149FAA /* TRTCChatSalon.m */; }; + 40EC853225E77AA500149FAA /* TRTCChatSalon.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851725E77AA500149FAA /* TRTCChatSalon.m */; }; + 40EC853325E77AA500149FAA /* TRTCChatSalon.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851725E77AA500149FAA /* TRTCChatSalon.m */; }; + 40EC853425E77AA500149FAA /* TXChatSalonBaseDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */; }; + 40EC853525E77AA500149FAA /* TXChatSalonBaseDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */; }; + 40EC853625E77AA500149FAA /* TXChatSalonBaseDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */; }; + 40EC853725E77AA500149FAA /* TXChatSalonBaseDef.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */; }; + 40EC856125E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */; }; + 40EC856225E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */; }; + 40EC856325E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */; }; + 40EC856425E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */; }; + 40EC856525E77D6F00149FAA /* TRTCChatSalonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */; }; + 40EC856625E77D6F00149FAA /* TRTCChatSalonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */; }; + 40EC856725E77D6F00149FAA /* TRTCChatSalonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */; }; + 40EC856825E77D6F00149FAA /* TRTCChatSalonManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */; }; + 40EC856925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */; }; + 40EC856A25E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */; }; + 40EC856B25E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */; }; + 40EC856C25E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */; }; + 40EC856D25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */; }; + 40EC856E25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */; }; + 40EC856F25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */; }; + 40EC857025E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */; }; + 40EC857125E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */; }; + 40EC857225E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */; }; + 40EC857325E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */; }; + 40EC857425E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */; }; + 40EC857525E77D6F00149FAA /* TRTCChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */; }; + 40EC857625E77D6F00149FAA /* TRTCChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */; }; + 40EC857725E77D6F00149FAA /* TRTCChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */; }; + 40EC857825E77D6F00149FAA /* TRTCChatSalonViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */; }; + 40EC857925E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */; }; + 40EC857A25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */; }; + 40EC857B25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */; }; + 40EC857C25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */; }; + 40EC857D25E77D6F00149FAA /* TRTCChatSalonSeatCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */; }; + 40EC857E25E77D6F00149FAA /* TRTCChatSalonSeatCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */; }; + 40EC857F25E77D6F00149FAA /* TRTCChatSalonSeatCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */; }; + 40EC858025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */; }; + 40EC858125E77D6F00149FAA /* TRTCChatSalonSeatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */; }; + 40EC858225E77D6F00149FAA /* TRTCChatSalonSeatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */; }; + 40EC858325E77D6F00149FAA /* TRTCChatSalonSeatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */; }; + 40EC858425E77D6F00149FAA /* TRTCChatSalonSeatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */; }; + 40EC858525E77D6F00149FAA /* TRTCChatSalonTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */; }; + 40EC858625E77D6F00149FAA /* TRTCChatSalonTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */; }; + 40EC858725E77D6F00149FAA /* TRTCChatSalonTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */; }; + 40EC858825E77D6F00149FAA /* TRTCChatSalonTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */; }; + 40EC858925E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */; }; + 40EC858A25E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */; }; + 40EC858B25E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */; }; + 40EC858C25E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */; }; + 40EC858D25E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */; }; + 40EC858E25E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */; }; + 40EC858F25E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */; }; + 40EC859025E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */; }; + 40EC859525E77D6F00149FAA /* TRTCCSAudienceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */; }; + 40EC859625E77D6F00149FAA /* TRTCCSAudienceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */; }; + 40EC859725E77D6F00149FAA /* TRTCCSAudienceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */; }; + 40EC859825E77D6F00149FAA /* TRTCCSAudienceListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */; }; + 40EC859925E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */; }; + 40EC859A25E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */; }; + 40EC859B25E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */; }; + 40EC859C25E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */; }; + 40EC859D25E77D6F00149FAA /* TRTCChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */; }; + 40EC859E25E77D6F00149FAA /* TRTCChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */; }; + 40EC859F25E77D6F00149FAA /* TRTCChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */; }; + 40EC85A025E77D6F00149FAA /* TRTCChatSalonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */; }; + 40EC85A125E77D6F00149FAA /* TRTCChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */; }; + 40EC85A225E77D6F00149FAA /* TRTCChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */; }; + 40EC85A325E77D6F00149FAA /* TRTCChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */; }; + 40EC85A425E77D6F00149FAA /* TRTCChatSalonRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */; }; + 40EC85A525E77D6F00149FAA /* TRTCChatSalonListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */; }; + 40EC85A625E77D6F00149FAA /* TRTCChatSalonListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */; }; + 40EC85A725E77D6F00149FAA /* TRTCChatSalonListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */; }; + 40EC85A825E77D6F00149FAA /* TRTCChatSalonListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */; }; + 40EC85A925E77D6F00149FAA /* TRTCChatSalonListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */; }; + 40EC85AA25E77D6F00149FAA /* TRTCChatSalonListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */; }; + 40EC85AB25E77D6F00149FAA /* TRTCChatSalonListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */; }; + 40EC85AC25E77D6F00149FAA /* TRTCChatSalonListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */; }; + 40EC85AD25E77D6F00149FAA /* TRTCChatSalonListRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */; }; + 40EC85AE25E77D6F00149FAA /* TRTCChatSalonListRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */; }; + 40EC85AF25E77D6F00149FAA /* TRTCChatSalonListRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */; }; + 40EC85B025E77D6F00149FAA /* TRTCChatSalonListRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */; }; + 40EC85B125E77D6F00149FAA /* TRTCChatSalonListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */; }; + 40EC85B225E77D6F00149FAA /* TRTCChatSalonListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */; }; + 40EC85B325E77D6F00149FAA /* TRTCChatSalonListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */; }; + 40EC85B425E77D6F00149FAA /* TRTCChatSalonListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */; }; + 40EC85B525E77D6F00149FAA /* TRTCChatSalonAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */; }; + 40EC85B625E77D6F00149FAA /* TRTCChatSalonAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */; }; + 40EC85B725E77D6F00149FAA /* TRTCChatSalonAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */; }; + 40EC85B825E77D6F00149FAA /* TRTCChatSalonAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */; }; 40EF362F24BC3FD0006AA4BB /* TRTCCloudAnction.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EF361F24BC3FCD006AA4BB /* TRTCCloudAnction.m */; }; 40EF363024BC3FD0006AA4BB /* TRTCCloudAnction.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EF361F24BC3FCD006AA4BB /* TRTCCloudAnction.m */; }; 40EF363124BC3FD0006AA4BB /* TRTCCloudAnction.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EF361F24BC3FCD006AA4BB /* TRTCCloudAnction.m */; }; @@ -667,7 +794,6 @@ 40EF364B24BC4134006AA4BB /* RoomManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EF364924BC4134006AA4BB /* RoomManager.swift */; }; 40EF364C24BC4134006AA4BB /* RoomManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EF364924BC4134006AA4BB /* RoomManager.swift */; }; 40EF364D24BC4134006AA4BB /* RoomManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40EF364924BC4134006AA4BB /* RoomManager.swift */; }; - 43DBDE22F893B0AC0B2BD98F /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 922771DDB1E733FCB8990068 /* ProfileViewController.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 4509E5D322816E8D001FF14A /* LiveRoomAccPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4509E5D222816E8D001FF14A /* LiveRoomAccPlayerView.m */; }; 4509E5D422816E8D001FF14A /* LiveRoomAccPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4509E5D222816E8D001FF14A /* LiveRoomAccPlayerView.m */; }; 4509E5D522816E8D001FF14A /* LiveRoomAccPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4509E5D222816E8D001FF14A /* LiveRoomAccPlayerView.m */; }; @@ -683,17 +809,6 @@ 4540802C23292D4400C3CAD5 /* PhotoUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 4540802B23292D4400C3CAD5 /* PhotoUtil.m */; }; 4540803C23292D4D00C3CAD5 /* PhotoUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 4540802B23292D4400C3CAD5 /* PhotoUtil.m */; }; 4540803D23292D4F00C3CAD5 /* PhotoUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 4540802B23292D4400C3CAD5 /* PhotoUtil.m */; }; - 455DA21C235566F600A5B146 /* RPNSegmenter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA211235566F400A5B146 /* RPNSegmenter.bundle */; }; - 455DA21F235566F600A5B146 /* AECore.metallib in Resources */ = {isa = PBXBuildFile; fileRef = 455DA212235566F400A5B146 /* AECore.metallib */; }; - 455DA222235566F600A5B146 /* poseest.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA213235566F400A5B146 /* poseest.bundle */; }; - 455DA225235566F600A5B146 /* FilterEngine.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA214235566F500A5B146 /* FilterEngine.bundle */; }; - 455DA228235566F600A5B146 /* detector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA215235566F500A5B146 /* detector.bundle */; }; - 455DA22B235566F600A5B146 /* ufa.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA216235566F500A5B146 /* ufa.bundle */; }; - 455DA22E235566F600A5B146 /* YTHandDetector.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 455DA217235566F500A5B146 /* YTHandDetector.bundle */; }; - 455DA231235566F600A5B146 /* v1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA218235566F500A5B146 /* v1 */; }; - 455DA234235566F600A5B146 /* u1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA219235566F500A5B146 /* u1 */; }; - 455DA237235566F600A5B146 /* o1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21A235566F500A5B146 /* o1 */; }; - 455DA23A235566F600A5B146 /* e1 in Resources */ = {isa = PBXBuildFile; fileRef = 455DA21B235566F500A5B146 /* e1 */; }; 45736EA2243F5DB800F7F601 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; 45736EA3243F5DB900F7F601 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; 45736EA4243F5DC000F7F601 /* TXLiteAVSDK_Professional.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45736E98243F5B2200F7F601 /* TXLiteAVSDK_Professional.framework */; }; @@ -723,7 +838,6 @@ 51A289FB230FB95800B9B73F /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51A289F8230FB93A00B9B73F /* OpenAL.framework */; }; 51A289FC230FB96000B9B73F /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51A289F8230FB93A00B9B73F /* OpenAL.framework */; }; 51CE9F98231944BE00B620BD /* OpenAL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51A289F8230FB93A00B9B73F /* OpenAL.framework */; }; - 5834E395256C92699317C6A7 /* LoginViewController_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2F673E343A0790C6D837163 /* LoginViewController_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 6A03ED411FD13DFB00F2F063 /* UIViewController+BackButtonHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A03ED3F1FD13DFB00F2F063 /* UIViewController+BackButtonHandler.m */; }; 6A03ED421FD13E0C00F2F063 /* UIViewController+BackButtonHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A03ED3F1FD13DFB00F2F063 /* UIViewController+BackButtonHandler.m */; }; 6A03ED431FD13E0C00F2F063 /* UIViewController+BackButtonHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A03ED3F1FD13DFB00F2F063 /* UIViewController+BackButtonHandler.m */; }; @@ -930,7 +1044,6 @@ 91F87A801FF4A101001644B1 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F87A7E1FF4A0FC001644B1 /* libsqlite3.tbd */; }; 91F87A811FF4A109001644B1 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F87A7E1FF4A0FC001644B1 /* libsqlite3.tbd */; }; 944B0A98D288A86246E2C14B /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; - 9BD5155FF907071F004F0DD9 /* ProfileViewController+UI.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA70CF5A96A183BB58F8A1A7 /* ProfileViewController+UI.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; A035040820D20A01007E61C6 /* QRCode.m in Sources */ = {isa = PBXBuildFile; fileRef = A035040720D20A01007E61C6 /* QRCode.m */; }; A035040920D20A01007E61C6 /* QRCode.m in Sources */ = {isa = PBXBuildFile; fileRef = A035040720D20A01007E61C6 /* QRCode.m */; }; A035040A20D20A01007E61C6 /* QRCode.m in Sources */ = {isa = PBXBuildFile; fileRef = A035040720D20A01007E61C6 /* QRCode.m */; }; @@ -991,10 +1104,14 @@ A0FFAD94213791B70087FF45 /* TVCHttpMessageURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = A0FFAD93213791B70087FF45 /* TVCHttpMessageURLProtocol.m */; }; A0FFAD96213791B70087FF45 /* TVCHttpMessageURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = A0FFAD93213791B70087FF45 /* TVCHttpMessageURLProtocol.m */; }; A0FFAD99213791B70087FF45 /* TVCHttpMessageURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = A0FFAD93213791B70087FF45 /* TVCHttpMessageURLProtocol.m */; }; - A29832F014F6BBA5548C3791 /* AppUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1025C61D3138181269BA1BB4 /* AppUtils.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - A33A3662EEE61EDFF61FED00 /* CommonUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58E4F2DCA417C17BCCABB14E /* CommonUtils.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; - AF1E5D5C6D7ADC8FA647EB99 /* ProfileManager_Mock.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF3881C83E9CDC5DC4D37350 /* ProfileManager_Mock.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + A5D87CD5EF580079C5540614 /* CommonUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A310BF0799B3A6B3B805D207 /* CommonUtils.swift */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; BD32F8A6AF7CC2FF9A53096E /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; + C600497825ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */; }; + C600497925ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */; }; + C600497A25ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */; }; + C600497B25ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */; }; + C667B8DB25F7151400B099FC /* AppPortalLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = C667B8DE25F7151400B099FC /* AppPortalLocalized.strings */; }; + C667B8DC25F7151400B099FC /* AppPortalLocalized.strings in Resources */ = {isa = PBXBuildFile; fileRef = C667B8DE25F7151400B099FC /* AppPortalLocalized.strings */; }; CE01F53E206DDE060056D693 /* VideoCompressPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE01F53D206DDE060056D693 /* VideoCompressPreviewController.m */; }; CE01F53F206DDE060056D693 /* VideoCompressPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE01F53D206DDE060056D693 /* VideoCompressPreviewController.m */; }; CE01F541206DDE060056D693 /* VideoCompressPreviewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CE01F53D206DDE060056D693 /* VideoCompressPreviewController.m */; }; @@ -1383,9 +1500,11 @@ /* Begin PBXFileReference section */ 00809C5850F41459EC8EE3D8 /* libPods-TXReplaykitUpload_Professional.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TXReplaykitUpload_Professional.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1025C61D3138181269BA1BB4 /* AppUtils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AppUtils.swift; sourceTree = ""; }; + 05725444B653F4415E5FB879 /* LoginViewController_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LoginViewController_Mock.swift; sourceTree = ""; }; 2840D91B24B8562200723FBC /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; 2840D92824B85E2A00723FBC /* SDWebImagePlaceholderImageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImagePlaceholderImageManager.swift; sourceTree = ""; }; + 2CE9060FD1C67F1E97A6A8B2 /* ProfileViewController+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "ProfileViewController+UI.swift"; sourceTree = ""; }; + 3FF8387DBA07E8B109025674 /* ProfileManager_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfileManager_Mock.swift; sourceTree = ""; }; 4009207D1F4FCBBE009B882D /* TXLiteAVDemo_Professional.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TXLiteAVDemo_Professional.app; sourceTree = BUILT_PRODUCTS_DIR; }; 4011CC0E24E4DDB600C543D7 /* TRTCCallingCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCallingCell.swift; sourceTree = ""; }; 4011CC0F24E4DDB600C543D7 /* CallUserModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallUserModel.swift; sourceTree = ""; }; @@ -1403,6 +1522,18 @@ 4011CC1D24E4DDB600C543D7 /* TRTCCallingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCCallingHeader.h; sourceTree = ""; }; 4011CC1E24E4DDB600C543D7 /* TRTCCalling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCCalling.h; sourceTree = ""; }; 401A9B3D247FCC7600C0763B /* AudioEffectSettingKit.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = AudioEffectSettingKit.xcodeproj; sourceTree = ""; }; + 4024558225FF9A0500267B13 /* v1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = v1; sourceTree = ""; }; + 4024558325FF9A0600267B13 /* YTHandDetector.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = YTHandDetector.bundle; sourceTree = ""; }; + 4024558425FF9A0600267B13 /* e1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = e1; sourceTree = ""; }; + 4024558525FF9A0600267B13 /* poseest.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = poseest.bundle; sourceTree = ""; }; + 4024558625FF9A0600267B13 /* o1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = o1; sourceTree = ""; }; + 4024558725FF9A0600267B13 /* AECore.metallib */ = {isa = PBXFileReference; lastKnownFileType = "archive.metal-library"; path = AECore.metallib; sourceTree = ""; }; + 4024558825FF9A0600267B13 /* MSFMLandmarks46_relandmark_models.xbin */ = {isa = PBXFileReference; lastKnownFileType = file; path = MSFMLandmarks46_relandmark_models.xbin; sourceTree = ""; }; + 4024558925FF9A0600267B13 /* FilterEngine.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = FilterEngine.bundle; sourceTree = ""; }; + 4024558A25FF9A0600267B13 /* RPNSegmenter.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = RPNSegmenter.bundle; sourceTree = ""; }; + 4024558B25FF9A0600267B13 /* u1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = u1; sourceTree = ""; }; + 4024558C25FF9A0700267B13 /* ufa.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = ufa.bundle; sourceTree = ""; }; + 4024558D25FF9A0700267B13 /* detector.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = detector.bundle; sourceTree = ""; }; 402A00DD2450552E0037A219 /* TXLiteAVDemo-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TXLiteAVDemo-Bridging-Header.h"; sourceTree = ""; }; 402A00EC24506B7C0037A219 /* UGCRecordWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UGCRecordWrapper.h; sourceTree = ""; }; 402A00ED24506B7C0037A219 /* UGCRecordWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UGCRecordWrapper.m; sourceTree = ""; }; @@ -1527,7 +1658,46 @@ 40B3F9FE2447042C000C37A3 /* HUDHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HUDHelper.h; sourceTree = ""; }; 40B3FA002447056D000C37A3 /* UIColor+MLPFlatColors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+MLPFlatColors.m"; sourceTree = ""; }; 40B3FA012447056D000C37A3 /* UIColor+MLPFlatColors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MLPFlatColors.h"; sourceTree = ""; }; + 40BE0EED25EF724600C58D6C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/TRTCChatSalonDemoLocalized.strings; sourceTree = ""; }; + 40BE0EF625EF724C00C58D6C /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/TRTCChatSalonDemoLocalized.strings"; sourceTree = ""; }; + 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonLocalized.swift; sourceTree = ""; }; + 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonTakeSeatTipsView.swift; sourceTree = ""; }; 40E25FCC2480C796005EB543 /* Portal+Swift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Portal+Swift.swift"; sourceTree = ""; }; + 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRTCChatSalonDef.m; sourceTree = ""; }; + 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChatSalonTRTCService.m; sourceTree = ""; }; + 40EC851125E77AA500149FAA /* ChatSalonTRTCService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChatSalonTRTCService.h; sourceTree = ""; }; + 40EC851325E77AA500149FAA /* TXChatSalonService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXChatSalonService.m; sourceTree = ""; }; + 40EC851425E77AA500149FAA /* TXChatSalonIMJsonHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXChatSalonIMJsonHandle.h; sourceTree = ""; }; + 40EC851525E77AA500149FAA /* TXChatSalonService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXChatSalonService.h; sourceTree = ""; }; + 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXChatSalonIMJsonHandle.m; sourceTree = ""; }; + 40EC851725E77AA500149FAA /* TRTCChatSalon.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRTCChatSalon.m; sourceTree = ""; }; + 40EC851925E77AA500149FAA /* TXChatSalonCommonDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXChatSalonCommonDef.h; sourceTree = ""; }; + 40EC851A25E77AA500149FAA /* TXChatSalonBaseDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXChatSalonBaseDef.h; sourceTree = ""; }; + 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXChatSalonBaseDef.m; sourceTree = ""; }; + 40EC851C25E77AA500149FAA /* TRTCChatSalon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCChatSalon.h; sourceTree = ""; }; + 40EC851D25E77AA500149FAA /* TRTCChatSalonDef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCChatSalonDef.h; sourceTree = ""; }; + 40EC851E25E77AA500149FAA /* TRTCChatSalonDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCChatSalonDelegate.h; sourceTree = ""; }; + 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonEnteryControl.swift; sourceTree = ""; }; + 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonManager.swift; sourceTree = ""; }; + 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCreateChatSalonViewModel.swift; sourceTree = ""; }; + 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCreateChatSalonViewController.swift; sourceTree = ""; }; + 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCreateChatSalonRootView.swift; sourceTree = ""; }; + 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonViewController.swift; sourceTree = ""; }; + 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonMainMenuView.swift; sourceTree = ""; }; + 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonSeatCell.swift; sourceTree = ""; }; + 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonSeatView.swift; sourceTree = ""; }; + 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonTipsView.swift; sourceTree = ""; }; + 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCSAudienceTableViewCell.swift; sourceTree = ""; }; + 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonTipsTableCell.swift; sourceTree = ""; }; + 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCCSAudienceListView.swift; sourceTree = ""; }; + 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonVIewDataDef.swift; sourceTree = ""; }; + 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonViewModel.swift; sourceTree = ""; }; + 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonRootView.swift; sourceTree = ""; }; + 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonListViewController.swift; sourceTree = ""; }; + 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonListCell.swift; sourceTree = ""; }; + 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonListRootView.swift; sourceTree = ""; }; + 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonListViewModel.swift; sourceTree = ""; }; + 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = TRTCChatSalonAssets.xcassets; sourceTree = ""; }; 40EF361E24BC3FCD006AA4BB /* TRTCCloudAnction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCCloudAnction.h; sourceTree = ""; }; 40EF361F24BC3FCD006AA4BB /* TRTCCloudAnction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TRTCCloudAnction.m; sourceTree = ""; }; 40EF362124BC3FCD006AA4BB /* TRTCLiveRoomIMAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TRTCLiveRoomIMAction.h; sourceTree = ""; }; @@ -1593,17 +1763,6 @@ 450CFC2023AB5CC800A17FD0 /* VideoRecord.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = VideoRecord.xcassets; sourceTree = ""; }; 4540802A23292D4400C3CAD5 /* PhotoUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PhotoUtil.h; sourceTree = ""; }; 4540802B23292D4400C3CAD5 /* PhotoUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PhotoUtil.m; sourceTree = ""; }; - 455DA211235566F400A5B146 /* RPNSegmenter.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = RPNSegmenter.bundle; sourceTree = ""; }; - 455DA212235566F400A5B146 /* AECore.metallib */ = {isa = PBXFileReference; lastKnownFileType = "archive.metal-library"; path = AECore.metallib; sourceTree = ""; }; - 455DA213235566F400A5B146 /* poseest.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = poseest.bundle; sourceTree = ""; }; - 455DA214235566F500A5B146 /* FilterEngine.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = FilterEngine.bundle; sourceTree = ""; }; - 455DA215235566F500A5B146 /* detector.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = detector.bundle; sourceTree = ""; }; - 455DA216235566F500A5B146 /* ufa.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = ufa.bundle; sourceTree = ""; }; - 455DA217235566F500A5B146 /* YTHandDetector.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = YTHandDetector.bundle; sourceTree = ""; }; - 455DA218235566F500A5B146 /* v1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = v1; sourceTree = ""; }; - 455DA219235566F500A5B146 /* u1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = u1; sourceTree = ""; }; - 455DA21A235566F500A5B146 /* o1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = o1; sourceTree = ""; }; - 455DA21B235566F500A5B146 /* e1 */ = {isa = PBXFileReference; lastKnownFileType = file; path = e1; sourceTree = ""; }; 45736E98243F5B2200F7F601 /* TXLiteAVSDK_Professional.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = TXLiteAVSDK_Professional.framework; sourceTree = ""; }; 457FD2F821C7530C00EEB03F /* NSString+UISize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSString+UISize.h"; sourceTree = ""; }; 457FD2F921C7530C00EEB03F /* NSString+UISize.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSString+UISize.m"; sourceTree = ""; }; @@ -1618,7 +1777,6 @@ 45E74D9A23B22BCD00C22B31 /* ThemeConfigurator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ThemeConfigurator.m; sourceTree = ""; }; 51A289F8230FB93A00B9B73F /* OpenAL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenAL.framework; path = System/Library/Frameworks/OpenAL.framework; sourceTree = SDKROOT; }; 51A4AD391F1F8AE300B4A806 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; - 58E4F2DCA417C17BCCABB14E /* CommonUtils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommonUtils.swift; sourceTree = ""; }; 6A03ED3F1FD13DFB00F2F063 /* UIViewController+BackButtonHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+BackButtonHandler.m"; sourceTree = ""; }; 6A03ED401FD13DFB00F2F063 /* UIViewController+BackButtonHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+BackButtonHandler.h"; sourceTree = ""; }; 6A1C108A2281A674005D7BD9 /* PushLogView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushLogView.h; sourceTree = ""; }; @@ -1726,7 +1884,6 @@ 91EEB3492060AF6C00BD01DB /* DownloadViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DownloadViewController.h; sourceTree = ""; }; 91EEB34A2060AF6C00BD01DB /* DownloadViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DownloadViewController.m; sourceTree = ""; }; 91F87A7E1FF4A0FC001644B1 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; - 922771DDB1E733FCB8990068 /* ProfileViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = ""; }; A035040620D20A01007E61C6 /* QRCode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = QRCode.h; sourceTree = ""; }; A035040720D20A01007E61C6 /* QRCode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QRCode.m; sourceTree = ""; }; A035042E20D24F99007E61C6 /* AddressBarController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AddressBarController.h; sourceTree = ""; }; @@ -1764,8 +1921,12 @@ A0B8FC0A207E24F2008D7982 /* TVCUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TVCUtils.h; sourceTree = ""; }; A0FFAD92213791B70087FF45 /* TVCHttpMessageURLProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TVCHttpMessageURLProtocol.h; sourceTree = ""; }; A0FFAD93213791B70087FF45 /* TVCHttpMessageURLProtocol.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TVCHttpMessageURLProtocol.m; sourceTree = ""; }; - C05FC57FE01B46C47BAB4724 /* LoginViewController+UI_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "LoginViewController+UI_Mock.swift"; sourceTree = ""; }; - C2F673E343A0790C6D837163 /* LoginViewController_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LoginViewController_Mock.swift; sourceTree = ""; }; + A310BF0799B3A6B3B805D207 /* CommonUtils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CommonUtils.swift; sourceTree = ""; }; + AC01445D40A66EAACDE64424 /* ProfileViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = ""; }; + BBBBD9C13D61DA96FDFBCEA2 /* LoginViewController+UI_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "LoginViewController+UI_Mock.swift"; sourceTree = ""; }; + C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TRTCChatSalonHandsUpTipsView.swift; sourceTree = ""; }; + C667B8DD25F7151400B099FC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/AppPortalLocalized.strings"; sourceTree = ""; }; + C667B8E525F7151B00B099FC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/AppPortalLocalized.strings; sourceTree = ""; }; C8E643F175AE44DEDBA06255 /* Pods-TXReplaykitUpload_Professional.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TXReplaykitUpload_Professional.release.xcconfig"; path = "Target Support Files/Pods-TXReplaykitUpload_Professional/Pods-TXReplaykitUpload_Professional.release.xcconfig"; sourceTree = ""; }; CE01F53C206DDE060056D693 /* VideoCompressPreviewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VideoCompressPreviewController.h; sourceTree = ""; }; CE01F53D206DDE060056D693 /* VideoCompressPreviewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoCompressPreviewController.m; sourceTree = ""; }; @@ -1774,7 +1935,6 @@ CE59D391206CD11400583727 /* VideoCompressViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VideoCompressViewController.m; sourceTree = ""; }; CE7C6E4A1FC2C5320095663F /* FilterResource.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = FilterResource.bundle; sourceTree = ""; }; CF31F0EB1FBB2A7E0066BF7D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; - CF3881C83E9CDC5DC4D37350 /* ProfileManager_Mock.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ProfileManager_Mock.swift; sourceTree = ""; }; CF61F5551FD690FB007CDAF4 /* YTFaceSDK.licence */ = {isa = PBXFileReference; lastKnownFileType = file; path = YTFaceSDK.licence; sourceTree = ""; }; D50292D42272BAFE00C052B7 /* RoomUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomUtil.m; sourceTree = ""; }; D50292D52272BAFE00C052B7 /* RoomUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomUtil.h; sourceTree = ""; }; @@ -1834,7 +1994,7 @@ D6E5D1C120B7B62000812B2F /* ScreenPushViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenPushViewController.h; sourceTree = ""; }; D6E5D1C220B7B62000812B2F /* ScreenPushViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScreenPushViewController.m; sourceTree = ""; }; D8DAEDF58579402BA6271194 /* Pods-TXLiteAVDemo_Professional.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TXLiteAVDemo_Professional.debug.xcconfig"; path = "Target Support Files/Pods-TXLiteAVDemo_Professional/Pods-TXLiteAVDemo_Professional.debug.xcconfig"; sourceTree = ""; }; - EA70CF5A96A183BB58F8A1A7 /* ProfileViewController+UI.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "ProfileViewController+UI.swift"; sourceTree = ""; }; + DB08160F5F234CE7746B24A2 /* AppUtils.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AppUtils.swift; sourceTree = ""; }; EBEC989F47F9D57C638FDC46 /* Pods-TXReplaykitUpload_Professional.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TXReplaykitUpload_Professional.debug.xcconfig"; path = "Target Support Files/Pods-TXReplaykitUpload_Professional/Pods-TXReplaykitUpload_Professional.debug.xcconfig"; sourceTree = ""; }; FDD4BF2824A1F8AD0015388B /* VideoEditor.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = VideoEditor.xcassets; sourceTree = ""; }; FE920CB89622A1ED8E88E9B0 /* libPods-TXLiteAVDemo_Professional.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-TXLiteAVDemo_Professional.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1892,6 +2052,21 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3E104D9740C4FD087556B6AC /* Login */ = { + isa = PBXGroup; + children = ( + 05725444B653F4415E5FB879 /* LoginViewController_Mock.swift */, + 3FF8387DBA07E8B109025674 /* ProfileManager_Mock.swift */, + BBBBD9C13D61DA96FDFBCEA2 /* LoginViewController+UI_Mock.swift */, + DB08160F5F234CE7746B24A2 /* AppUtils.swift */, + A310BF0799B3A6B3B805D207 /* CommonUtils.swift */, + AC01445D40A66EAACDE64424 /* ProfileViewController.swift */, + 2CE9060FD1C67F1E97A6A8B2 /* ProfileViewController+UI.swift */, + ); + name = Login; + path = TXLiteAVDemo/Login; + sourceTree = SOURCE_ROOT; + }; 4011CC0C24E4DDB600C543D7 /* TRTCCallingDemo */ = { isa = PBXGroup; children = ( @@ -2267,6 +2442,15 @@ path = QRScan; sourceTree = ""; }; + 405397D825E63C3B00B61D5D /* TRTCChatSalonDemo */ = { + isa = PBXGroup; + children = ( + 40EC854425E77D6F00149FAA /* ui */, + 40EC850C25E77AA500149FAA /* model */, + ); + path = TRTCChatSalonDemo; + sourceTree = ""; + }; 405874162445AA10009B3503 /* SuperPlayerKit */ = { isa = PBXGroup; children = ( @@ -2503,6 +2687,139 @@ path = Views; sourceTree = ""; }; + 40EC850C25E77AA500149FAA /* model */ = { + isa = PBXGroup; + children = ( + 40EC850D25E77AA500149FAA /* Impl */, + 40EC851C25E77AA500149FAA /* TRTCChatSalon.h */, + 40EC851D25E77AA500149FAA /* TRTCChatSalonDef.h */, + 40EC851E25E77AA500149FAA /* TRTCChatSalonDelegate.h */, + ); + path = model; + sourceTree = ""; + }; + 40EC850D25E77AA500149FAA /* Impl */ = { + isa = PBXGroup; + children = ( + 40EC850E25E77AA500149FAA /* TRTCChatSalonDef.m */, + 40EC850F25E77AA500149FAA /* trtc */, + 40EC851225E77AA500149FAA /* chatsalon */, + 40EC851725E77AA500149FAA /* TRTCChatSalon.m */, + 40EC851825E77AA500149FAA /* base */, + ); + path = Impl; + sourceTree = ""; + }; + 40EC850F25E77AA500149FAA /* trtc */ = { + isa = PBXGroup; + children = ( + 40EC851025E77AA500149FAA /* ChatSalonTRTCService.m */, + 40EC851125E77AA500149FAA /* ChatSalonTRTCService.h */, + ); + path = trtc; + sourceTree = ""; + }; + 40EC851225E77AA500149FAA /* chatsalon */ = { + isa = PBXGroup; + children = ( + 40EC851325E77AA500149FAA /* TXChatSalonService.m */, + 40EC851425E77AA500149FAA /* TXChatSalonIMJsonHandle.h */, + 40EC851525E77AA500149FAA /* TXChatSalonService.h */, + 40EC851625E77AA500149FAA /* TXChatSalonIMJsonHandle.m */, + ); + path = chatsalon; + sourceTree = ""; + }; + 40EC851825E77AA500149FAA /* base */ = { + isa = PBXGroup; + children = ( + 40EC851925E77AA500149FAA /* TXChatSalonCommonDef.h */, + 40EC851A25E77AA500149FAA /* TXChatSalonBaseDef.h */, + 40EC851B25E77AA500149FAA /* TXChatSalonBaseDef.m */, + ); + path = base; + sourceTree = ""; + }; + 40EC854425E77D6F00149FAA /* ui */ = { + isa = PBXGroup; + children = ( + 40EC854525E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift */, + 40EC854625E77D6F00149FAA /* NetworkRoomManager */, + 40EC854825E77D6F00149FAA /* TRTCCreateChatSalonViewController */, + 40EC854C25E77D6F00149FAA /* TRTCChatSalonViewController */, + 40EC855A25E77D6F00149FAA /* TRTCChatSalonListViewController */, + 40EC856025E77D6F00149FAA /* TRTCChatSalonAssets.xcassets */, + 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */, + 40BE0EF725EF762F00C58D6C /* TRTCChatSalonLocalized.swift */, + ); + path = ui; + sourceTree = ""; + }; + 40EC854625E77D6F00149FAA /* NetworkRoomManager */ = { + isa = PBXGroup; + children = ( + 40EC854725E77D6F00149FAA /* TRTCChatSalonManager.swift */, + ); + path = NetworkRoomManager; + sourceTree = ""; + }; + 40EC854825E77D6F00149FAA /* TRTCCreateChatSalonViewController */ = { + isa = PBXGroup; + children = ( + 40EC854925E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift */, + 40EC854A25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift */, + 40EC854B25E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift */, + ); + path = TRTCCreateChatSalonViewController; + sourceTree = ""; + }; + 40EC854C25E77D6F00149FAA /* TRTCChatSalonViewController */ = { + isa = PBXGroup; + children = ( + 40EC854E25E77D6F00149FAA /* SubViews */, + 40EC854D25E77D6F00149FAA /* TRTCChatSalonViewController.swift */, + 40EC855725E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift */, + 40EC855825E77D6F00149FAA /* TRTCChatSalonViewModel.swift */, + 40EC855925E77D6F00149FAA /* TRTCChatSalonRootView.swift */, + ); + path = TRTCChatSalonViewController; + sourceTree = ""; + }; + 40EC854E25E77D6F00149FAA /* SubViews */ = { + isa = PBXGroup; + children = ( + 40EC854F25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift */, + 40EC855025E77D6F00149FAA /* TRTCChatSalonSeatCell.swift */, + 40EC855125E77D6F00149FAA /* TRTCChatSalonSeatView.swift */, + 40EC855225E77D6F00149FAA /* TRTCChatSalonTipsView.swift */, + 40EC855325E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift */, + 40EC855425E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift */, + 40EC855625E77D6F00149FAA /* TRTCCSAudienceListView.swift */, + 40E18DA625ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift */, + C600497725ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift */, + ); + path = SubViews; + sourceTree = ""; + }; + 40EC855A25E77D6F00149FAA /* TRTCChatSalonListViewController */ = { + isa = PBXGroup; + children = ( + 40EC855B25E77D6F00149FAA /* TRTCChatSalonListViewController.swift */, + 40EC855C25E77D6F00149FAA /* SubViews */, + 40EC855E25E77D6F00149FAA /* TRTCChatSalonListRootView.swift */, + 40EC855F25E77D6F00149FAA /* TRTCChatSalonListViewModel.swift */, + ); + path = TRTCChatSalonListViewController; + sourceTree = ""; + }; + 40EC855C25E77D6F00149FAA /* SubViews */ = { + isa = PBXGroup; + children = ( + 40EC855D25E77D6F00149FAA /* TRTCChatSalonListCell.swift */, + ); + path = SubViews; + sourceTree = ""; + }; 40EF361D24BC3FCD006AA4BB /* Impl */ = { isa = PBXGroup; children = ( @@ -2590,6 +2907,7 @@ 40B3F8DB2446E6C5000C37A3 /* Debug */, 4011CC0C24E4DDB600C543D7 /* TRTCCallingDemo */, 40B3F9252446E6C6000C37A3 /* TRTCLiveRoomDemo */, + 405397D825E63C3B00B61D5D /* TRTCChatSalonDemo */, 40B3F8F52446E6C5000C37A3 /* TRTCVoiceRoomDemo */, 4090F614246ADBBF00EA72A0 /* TRTCMeetingDemo */, 40F8531D1EE8FC1E00EE47D7 /* Supporting Files */, @@ -2605,7 +2923,7 @@ 402A00EA245068240037A219 /* UGCVideoJoinDemo */, 402A00E9245068160037A219 /* UGCVideoEditDemo */, 402A00E5245065500037A219 /* UGCVideoUploadDemo */, - 5887D08E8193CF54652FF1E9 /* Login */, + 3E104D9740C4FD087556B6AC /* Login */, ); path = TXLiteAVDemo; sourceTree = ""; @@ -2766,21 +3084,6 @@ path = UGCUpload; sourceTree = ""; }; - 5887D08E8193CF54652FF1E9 /* Login */ = { - isa = PBXGroup; - children = ( - C2F673E343A0790C6D837163 /* LoginViewController_Mock.swift */, - CF3881C83E9CDC5DC4D37350 /* ProfileManager_Mock.swift */, - C05FC57FE01B46C47BAB4724 /* LoginViewController+UI_Mock.swift */, - 1025C61D3138181269BA1BB4 /* AppUtils.swift */, - 58E4F2DCA417C17BCCABB14E /* CommonUtils.swift */, - 922771DDB1E733FCB8990068 /* ProfileViewController.swift */, - EA70CF5A96A183BB58F8A1A7 /* ProfileViewController+UI.swift */, - ); - name = Login; - path = TXLiteAVDemo/Login; - sourceTree = SOURCE_ROOT; - }; 6AAEC24D2497807100B57D86 /* ui */ = { isa = PBXGroup; children = ( @@ -3421,10 +3724,12 @@ 40B5C6962484BE5700D3A718 /* AudioEffectSettingKitResources.bundle in Resources */, 40A7CFD9245FC0CF00E792A5 /* TRTCLiveRoomDemo.xcassets in Resources */, 40A49D7524598DA800BFCB18 /* UGCKitResources.bundle in Resources */, + 40BE0EEA25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings in Resources */, 4040CC5E2497C79400CA4FAA /* TRTCVoiceRoomAssets.xcassets in Resources */, 450CFC4D23AB5CC800A17FD0 /* VideoRecord.xcassets in Resources */, 7B5A2DBD25B0355400B4B469 /* V2QRGenerateViewController.xib in Resources */, D6BEF6F22040307E00CBE2BD /* VideoJoinerCell.xib in Resources */, + 40EC85B625E77D6F00149FAA /* TRTCChatSalonAssets.xcassets in Resources */, 40A7CFEF2461102E00E792A5 /* SuperPlayer.bundle in Resources */, 400920241F4FCBBE009B882D /* LaunchScreen.storyboard in Resources */, 4009202D1F4FCBBE009B882D /* Assets.xcassets in Resources */, @@ -3550,7 +3855,11 @@ 6AAEC2A82497807200B57D86 /* TRTCMeetingMoreViewController.swift in Sources */, 400C953D2449565400600BF0 /* HUDHelper.m in Sources */, 400C9539244955A000600BF0 /* TCLog.m in Sources */, + 40EC85A625E77D6F00149FAA /* TRTCChatSalonListViewController.swift in Sources */, + 40EC85AE25E77D6F00149FAA /* TRTCChatSalonListRootView.swift in Sources */, 4040CC762497C79400CA4FAA /* TRTCVoiceRoomEnteryControl.swift in Sources */, + 40EC856E25E77D6F00149FAA /* TRTCCreateChatSalonViewController.swift in Sources */, + 40EC85A225E77D6F00149FAA /* TRTCChatSalonRootView.swift in Sources */, 4040CCAE2497C79400CA4FAA /* TRTCVoiceRoomListCell.swift in Sources */, 400C953C244955A000600BF0 /* TCUtil.m in Sources */, 40E1F43E2468F72900F3D350 /* UIColor+MLPFlatColors.m in Sources */, @@ -3563,9 +3872,12 @@ 40EF363024BC3FD0006AA4BB /* TRTCCloudAnction.m in Sources */, 4046B16224B36C0A00F27349 /* TRTCLog.swift in Sources */, 4040CC6E2497C79400CA4FAA /* TRTCVoiceRoomViewModel.swift in Sources */, + 40EC853525E77AA500149FAA /* TXChatSalonBaseDef.m in Sources */, 4040CCA62497C79400CA4FAA /* TRTCVoiceRoomListViewController.swift in Sources */, + 40EC853125E77AA500149FAA /* TRTCChatSalon.m in Sources */, 6AAEC2B02497807200B57D86 /* TRTCMeetingMemberViewController.swift in Sources */, 40C0BDD4244853FF00931313 /* LiveRoomMainViewController.swift in Sources */, + 40BE0EF925EF762F00C58D6C /* TRTCChatSalonLocalized.swift in Sources */, 40C0BDD5244853FF00931313 /* TCStatusInfoView.m in Sources */, 40C0BDD6244853FF00931313 /* TCPlaceHolderTextView.m in Sources */, 40C0BDD7244853FF00931313 /* TCMsgListCell.m in Sources */, @@ -3591,6 +3903,8 @@ 40C0BDE1244853FF00931313 /* TCAnchorViewController+LiveDelegate.swift in Sources */, 6AAEC2A42497807200B57D86 /* TRTCMeetingMoreViewShareVC.swift in Sources */, 40E1F44A2468F74E00F3D350 /* NSDictionary+Common.m in Sources */, + 40EC859E25E77D6F00149FAA /* TRTCChatSalonViewModel.swift in Sources */, + 40EC856625E77D6F00149FAA /* TRTCChatSalonManager.swift in Sources */, 40C0BDE2244853FF00931313 /* TCAudienceViewController.m in Sources */, 40E1F4452468F74600F3D350 /* NSString+UISize.m in Sources */, 40C0BDE3244853FF00931313 /* TCAudienceViewController+LiveDelegate.swift in Sources */, @@ -3606,8 +3920,12 @@ 402A00FE24506D0D0037A219 /* UGCVideoUploadWrapper.m in Sources */, 7B5A2DBF25B0355400B4B469 /* V2MainItemCell.m in Sources */, 6AAEC28C2497807200B57D86 /* TRTCMeetingMoreViewVideoVC.swift in Sources */, + 40EC856A25E77D6F00149FAA /* TRTCCreateChatSalonViewModel.swift in Sources */, 6AAEC27C2497807200B57D86 /* TRTCMeetingMainViewController+CollectionView.swift in Sources */, + 40EC858E25E77D6F00149FAA /* TRTCChatSalonTipsTableCell.swift in Sources */, 6AAEC2C02497807200B57D86 /* IMProtocol.m in Sources */, + 40EC858625E77D6F00149FAA /* TRTCChatSalonTipsView.swift in Sources */, + 40EC858A25E77D6F00149FAA /* TRTCCSAudienceTableViewCell.swift in Sources */, 40C0BDBF2448539500931313 /* GenerateTestUserSig.m in Sources */, D541372C22795FAA006D9C9D /* IMMsgManager.m in Sources */, D541372D22795FAA006D9C9D /* RoomUtil.m in Sources */, @@ -3627,6 +3945,7 @@ D541373522795FAA006D9C9D /* LiveRoomTableViewCell.m in Sources */, D541373622795FAA006D9C9D /* MLVBLiveRoom.m in Sources */, D541373722795FAA006D9C9D /* MLVBLiveRoomDef.m in Sources */, + 40EC857225E77D6F00149FAA /* TRTCCreateChatSalonRootView.swift in Sources */, 7B5A2DDB25B0355400B4B469 /* UILabel+V2.m in Sources */, 4040CCB62497C79400CA4FAA /* TRTCCreateVoiceRoomRootView.swift in Sources */, 7B5A2DC325B0355400B4B469 /* V2MainProtocolSelectViewController.m in Sources */, @@ -3634,6 +3953,7 @@ 45E74D9C23B22BCD00C22B31 /* ThemeConfigurator.m in Sources */, D541373822795FAA006D9C9D /* PlayViewController.m in Sources */, 6AAEC2742497807200B57D86 /* CenterSegmentView.swift in Sources */, + 40EC858225E77D6F00149FAA /* TRTCChatSalonSeatView.swift in Sources */, 7B5A2DE325B0355400B4B469 /* V2MainViewController.m in Sources */, 4040CC9A2497C79400CA4FAA /* TRTCVoiceRoomMsgInputView.swift in Sources */, D541373922795FAA006D9C9D /* CameraPushViewController.m in Sources */, @@ -3642,18 +3962,23 @@ 4040CC822497C79400CA4FAA /* TRTCVoiceRoomSeatCell.swift in Sources */, 4040CC922497C79400CA4FAA /* TRTCAudienceTableViewCell.swift in Sources */, D541373C22795FAA006D9C9D /* TXCAudioCustomRecorder.m in Sources */, + 40EC859625E77D6F00149FAA /* TRTCCSAudienceListView.swift in Sources */, + 40EC859A25E77D6F00149FAA /* TRTCChatSalonVIewDataDef.swift in Sources */, D541373D22795FAA006D9C9D /* PushBgmControl.m in Sources */, 91DB2F01212554B500013D74 /* SuperPlayerGuideView.m in Sources */, A0B8FBF0207E2352008D7982 /* TXUGCPublish.m in Sources */, 6AAEC2802497807200B57D86 /* TRTCBroadcastExtensionLauncher.swift in Sources */, 4509E5D422816E8D001FF14A /* LiveRoomAccPlayerView.m in Sources */, + 40EC852925E77AA500149FAA /* TXChatSalonService.m in Sources */, 40091F781F4FCBBE009B882D /* UIButton+Glossy.m in Sources */, 7B5A2DE725B0355400B4B469 /* V2LiveUtils.m in Sources */, + 40EC857A25E77D6F00149FAA /* TRTCChatSalonMainMenuView.swift in Sources */, 912A62322160D78A00C16E41 /* CFDanmakuView.m in Sources */, A06D38DE2130042E00E3210E /* TXUGCPublishOptCenter.m in Sources */, 40091F7D1F4FCBBE009B882D /* ScanQRController.mm in Sources */, 7B5A2DD325B0355400B4B469 /* V2SettingsContainerViewController.m in Sources */, 6A3105DB22682A06002F6115 /* ImageUploadViewController.m in Sources */, + 40EC852125E77AA500149FAA /* TRTCChatSalonDef.m in Sources */, 4046B15524B36AD700F27349 /* TXVoiceRoomIMJsonHandle.m in Sources */, D6BEF7582040353E00CBE2BD /* ListVideoCell.m in Sources */, 912A620E2160D78A00C16E41 /* CFDanmaku.m in Sources */, @@ -3663,12 +3988,15 @@ D6BEF6EF2040307E00CBE2BD /* VideoJoinerCell.m in Sources */, 6AAEC2782497807200B57D86 /* TRTCMeetingConst.swift in Sources */, 4011CC3024E4DDB600C543D7 /* TRTCCallingContactViewController.swift in Sources */, + C600497925ECE75C00EAEB17 /* TRTCChatSalonHandsUpTipsView.swift in Sources */, 4011CC2424E4DDB600C543D7 /* CallUserModel.swift in Sources */, 4011CC4424E4DDB600C543D7 /* TRTCCalling+Signal.m in Sources */, 45D8448E23B64395001CD3A9 /* UGCUploadList.m in Sources */, + 40EC856225E77D6F00149FAA /* TRTCChatSalonEnteryControl.swift in Sources */, 6AAEC2842497807200B57D86 /* TRTCMeetingMainViewController+UI.swift in Sources */, 4041832D2455854200DD70AB /* V8HorizontalPickerView.m in Sources */, D6BEF6BF20401BD900CBE2BD /* VideoPreview.m in Sources */, + 40EC85AA25E77D6F00149FAA /* TRTCChatSalonListCell.swift in Sources */, A0B8FBF8207E2352008D7982 /* TVCClient.m in Sources */, D6BEF6572040179600CBE2BD /* VideoPreviewViewController.m in Sources */, A0B8FBEC207E2352008D7982 /* TVCClientInner.m in Sources */, @@ -3703,6 +4031,8 @@ 45BB0B3923A9C3730084FE90 /* UGCKitWrapper.m in Sources */, 40091F951F4FCBBE009B882D /* UIButton+Additions.m in Sources */, 2840D92E24B8801800723FBC /* SDWebImagePlaceholderImageManager.swift in Sources */, + 40EC852D25E77AA500149FAA /* TXChatSalonIMJsonHandle.m in Sources */, + 40E18DA825ECC2B7002F7CD9 /* TRTCChatSalonTakeSeatTipsView.swift in Sources */, 6AAEC2902497807200B57D86 /* TRTCMeetingMemberController+UI.swift in Sources */, D6BEF6E92040307E00CBE2BD /* VideoEditPrevController.m in Sources */, 40091F981F4FCBBE009B882D /* UIView+CustomAutoLayout.m in Sources */, @@ -3725,24 +4055,28 @@ 7B5A2DD725B0355400B4B469 /* UISegmentedControl+V2.m in Sources */, A035040920D20A01007E61C6 /* QRCode.m in Sources */, 402A010224506F740037A219 /* main.m in Sources */, + 40EC852525E77AA500149FAA /* ChatSalonTRTCService.m in Sources */, 40091FA51F4FCBBE009B882D /* UIImage+Additions.m in Sources */, 4540803C23292D4D00C3CAD5 /* PhotoUtil.m in Sources */, 912A62202160D78A00C16E41 /* CFDanmakuInfo.m in Sources */, 45CC58AD246290BB002A914E /* SimpleIPC.m in Sources */, + 40EC857E25E77D6F00149FAA /* TRTCChatSalonSeatCell.swift in Sources */, A0B8FBE8207E2352008D7982 /* TVCCommon.m in Sources */, + 40EC857625E77D6F00149FAA /* TRTCChatSalonViewController.swift in Sources */, 7B5A2DDF25B0355400B4B469 /* V2QRGenerateViewController.m in Sources */, + 40EC85B225E77D6F00149FAA /* TRTCChatSalonListViewModel.swift in Sources */, 4040CC962497C79400CA4FAA /* TRTCVoiceRoomTipsTableCell.swift in Sources */, 4046B15924B36AD700F27349 /* TXBaseDef.m in Sources */, 7B5A2DC125B0355400B4B469 /* V2QRScanViewController.m in Sources */, D6BEF75B2040353E00CBE2BD /* MoviePlayerViewController.m in Sources */, 7B5A2DCD25B0355400B4B469 /* V2MainProtocolSelectSegmentView.m in Sources */, - 5834E395256C92699317C6A7 /* LoginViewController_Mock.swift in Sources */, - AF1E5D5C6D7ADC8FA647EB99 /* ProfileManager_Mock.swift in Sources */, - 177CC32C2A559AF6A5193DF1 /* LoginViewController+UI_Mock.swift in Sources */, - A29832F014F6BBA5548C3791 /* AppUtils.swift in Sources */, - A33A3662EEE61EDFF61FED00 /* CommonUtils.swift in Sources */, - 43DBDE22F893B0AC0B2BD98F /* ProfileViewController.swift in Sources */, - 9BD5155FF907071F004F0DD9 /* ProfileViewController+UI.swift in Sources */, + 3B62B23CE22937D37BE1E8B9 /* LoginViewController_Mock.swift in Sources */, + 16C9F6315A0B86B5186D8070 /* ProfileManager_Mock.swift in Sources */, + 1A3781E466CB5454F31BF136 /* LoginViewController+UI_Mock.swift in Sources */, + 2D14F385032F832FF7E38644 /* AppUtils.swift in Sources */, + A5D87CD5EF580079C5540614 /* CommonUtils.swift in Sources */, + 2366FA9BBE88A1C08D73AF1E /* ProfileViewController.swift in Sources */, + 338E38575707B25D2EC253D6 /* ProfileViewController+UI.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3781,6 +4115,15 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 40BE0EEE25EF724600C58D6C /* TRTCChatSalonDemoLocalized.strings */ = { + isa = PBXVariantGroup; + children = ( + 40BE0EED25EF724600C58D6C /* en */, + 40BE0EF625EF724C00C58D6C /* zh-Hans */, + ); + name = TRTCChatSalonDemoLocalized.strings; + sourceTree = ""; + }; 40F853311EE8FC9B00EE47D7 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -3797,6 +4140,15 @@ name = Main.storyboard; sourceTree = ""; }; + C667B8DE25F7151400B099FC /* AppPortalLocalized.strings */ = { + isa = PBXVariantGroup; + children = ( + C667B8DD25F7151400B099FC /* zh-Hans */, + C667B8E525F7151B00B099FC /* en */, + ); + name = AppPortalLocalized.strings; + sourceTree = ""; + }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/Demo/TXLiteAVDemo/App/Info.plist b/Demo/TXLiteAVDemo/App/Info.plist index f739243d..fa4bd06d 100644 --- a/Demo/TXLiteAVDemo/App/Info.plist +++ b/Demo/TXLiteAVDemo/App/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 8.4.672 + 8.5.670 CFBundleSignature ???? CFBundleURLTypes @@ -36,7 +36,7 @@ CFBundleVersion - 672 + 670 IMSDKCrashReporterEnable LSRequiresIPhoneOS diff --git a/Demo/TXLiteAVDemo/App/Main/MainViewController.m b/Demo/TXLiteAVDemo/App/Main/MainViewController.m index 0624b60b..c029a397 100644 --- a/Demo/TXLiteAVDemo/App/Main/MainViewController.m +++ b/Demo/TXLiteAVDemo/App/Main/MainViewController.m @@ -178,9 +178,11 @@ - (void)initCellInfos controllerClassName:@"PlayViewController"]; [subCells addObject:scellInfo]; #endif +#ifndef SMART scellInfo = [CellInfo cellInfoWithTitle:@"连麦演示(新方案)" controllerClassName:@"V2MainViewController"]; [subCells addObject:scellInfo]; +#endif scellInfo = [CellInfo cellInfoWithTitle:@"连麦演示(旧方案)" controllerClassName:@"LiveRoomListViewController"]; diff --git a/Demo/TXLiteAVDemo/App/Resource/Assets.xcassets/Main/Contents.json b/Demo/TXLiteAVDemo/App/Resource/Assets.xcassets/Main/Contents.json index da4a164c..73c00596 100644 --- a/Demo/TXLiteAVDemo/App/Resource/Assets.xcassets/Main/Contents.json +++ b/Demo/TXLiteAVDemo/App/Resource/Assets.xcassets/Main/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Demo/TXLiteAVDemo/App/TRTC-Appstore-Info.plist b/Demo/TXLiteAVDemo/App/TRTC-Appstore-Info.plist index 1490907a..9340c1ed 100644 --- a/Demo/TXLiteAVDemo/App/TRTC-Appstore-Info.plist +++ b/Demo/TXLiteAVDemo/App/TRTC-Appstore-Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 8.4.672 + 8.5.670 CFBundleSignature BNDL CFBundleURLTypes @@ -36,7 +36,7 @@ CFBundleVersion - 672 + 670 IMSDKCrashReporterEnable LSRequiresIPhoneOS diff --git a/Demo/TXLiteAVDemo/App/TXLiteAVDemo-Bridging-Header.h b/Demo/TXLiteAVDemo/App/TXLiteAVDemo-Bridging-Header.h index 8aaa1fcb..6cf5d6cc 100644 --- a/Demo/TXLiteAVDemo/App/TXLiteAVDemo-Bridging-Header.h +++ b/Demo/TXLiteAVDemo/App/TXLiteAVDemo-Bridging-Header.h @@ -17,8 +17,13 @@ #import "TCAnchorViewController.h" #import "TCAudienceViewController.h" #import "TRTCMeeting.h" +// VocieRoom #import "TRTCVoiceRoomDef.h" #import "TRTCVoiceRoom.h" +// ChatSalon +#import "TRTCChatSalon.h" +#import "TRTCChatSalonDef.h" + #import "TRTCLiveRoom.h" #import "TRTCCalling.h" #endif diff --git a/Demo/TXLiteAVDemo/AudioSettingKit/AudioEffectSettingKit.xcodeproj/project.pbxproj b/Demo/TXLiteAVDemo/AudioSettingKit/AudioEffectSettingKit.xcodeproj/project.pbxproj index 6b697a70..74147855 100644 --- a/Demo/TXLiteAVDemo/AudioSettingKit/AudioEffectSettingKit.xcodeproj/project.pbxproj +++ b/Demo/TXLiteAVDemo/AudioSettingKit/AudioEffectSettingKit.xcodeproj/project.pbxproj @@ -62,7 +62,7 @@ 40E25FB6248029F8005EB543 /* ASNSLayoutConstraint+MASDebugAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 40E25F9D248029F8005EB543 /* ASNSLayoutConstraint+MASDebugAdditions.m */; }; 40E25FB924803F68005EB543 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 401A9A47247FB78F00C0763B /* libc++.tbd */; }; 40E25FBE24804490005EB543 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; }; - F8AEE9CB13995851D47C3C9E /* TXLiteAVSDK_Professional.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6C82D50F8BE5417AD502422B /* TXLiteAVSDK_Professional.framework */; }; + FBADCDA2B8C83A504A84A058 /* TXLiteAVSDK_Professional.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD423571D49C3A35675C70E8 /* TXLiteAVSDK_Professional.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -130,7 +130,7 @@ 40E25F9B248029F8005EB543 /* ASMASLayoutConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMASLayoutConstraint.h; sourceTree = ""; }; 40E25F9C248029F8005EB543 /* ASViewController+MASAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASViewController+MASAdditions.h"; sourceTree = ""; }; 40E25F9D248029F8005EB543 /* ASNSLayoutConstraint+MASDebugAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ASNSLayoutConstraint+MASDebugAdditions.m"; sourceTree = ""; }; - 6C82D50F8BE5417AD502422B /* TXLiteAVSDK_Professional.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXLiteAVSDK_Professional.framework; path = ../../../SDK/TXLiteAVSDK_Professional.framework; sourceTree = ""; }; + BD423571D49C3A35675C70E8 /* TXLiteAVSDK_Professional.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXLiteAVSDK_Professional.framework; path = ../../../SDK/TXLiteAVSDK_Professional.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -142,7 +142,7 @@ 40E25FBE24804490005EB543 /* BuildFile in Frameworks */, 40E25FB924803F68005EB543 /* libc++.tbd in Frameworks */, 40D08707249C9D460055F9A6 /* AssetsLibrary.framework in Frameworks */, - F8AEE9CB13995851D47C3C9E /* TXLiteAVSDK_Professional.framework in Frameworks */, + FBADCDA2B8C83A504A84A058 /* TXLiteAVSDK_Professional.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -199,7 +199,7 @@ 40D08706249C9D460055F9A6 /* AssetsLibrary.framework */, 40D08703249C9C130055F9A6 /* Accelerate.framework */, 401A9A47247FB78F00C0763B /* libc++.tbd */, - 6C82D50F8BE5417AD502422B /* TXLiteAVSDK_Professional.framework */, + BD423571D49C3A35675C70E8 /* TXLiteAVSDK_Professional.framework */, ); name = Frameworks; sourceTree = ""; diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PlayerViewController.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PlayerViewController.m index 184f3364..6e1be07e 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PlayerViewController.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PlayerViewController.m @@ -15,6 +15,7 @@ #import "V2PlayerSettingViewController.h" #import "V2LiveUtils.h" #import "MBProgressHUD.h" +#import "PhotoUtil.h" #define V2LogSimple() \ @@ -212,6 +213,7 @@ - (V2TXLiveCode)startPlayInner:(BOOL)start { self.hasRecvFirstFrame = NO; result = [self.player startPlay:self.url]; if (result == V2TXLIVE_OK) { + [self showLoading:@"加载中..." withDetailText:@"请等待"]; // [self.settingContainer clearSettingVC]; /// 开始播放后,超过5秒未收到首帧视频,则提示播放失败,并退出播放。 if (self.delayBlock) { @@ -223,6 +225,7 @@ - (V2TXLiveCode)startPlayInner:(BOOL)start { if (!weakSelf.hasRecvFirstFrame) { [weakSelf showText:@"获取视频帧超时" withDetailText:nil]; [weakSelf startPlayInner:NO]; + [weakSelf hiddeLoading]; } }); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), self.delayBlock); @@ -426,12 +429,36 @@ - (void)hiddeLoading { } #pragma mark - V2TXLivePlayerObserver -- (void)onRecvFirstAudioFrame:(id)player { - self.hasRecvFirstFrame = YES; +- (void)onAudioPlayStatusUpdate:(id)player status:(V2TXLivePlayStatus)status reason:(V2TXLiveStatusChangeReason)reason extraInfo:(NSDictionary *)extraInfo { + switch (status) { + case V2TXLivePlayStatusPlaying: + self.hasRecvFirstFrame = YES; + [self hiddeLoading]; + V2LogSimple() + break; + case V2TXLivePlayStatusLoading: + [self showLoading:@"加载中..." withDetailText:@"请等待"]; + V2LogSimple() + break; + default: + break; + } } -- (void)onRecvFirstVideoFrame:(id)player { - self.hasRecvFirstFrame = YES; +- (void)onVideoPlayStatusUpdate:(id)player status:(V2TXLivePlayStatus)status reason:(V2TXLiveStatusChangeReason)reason extraInfo:(NSDictionary *)extraInfo { + switch (status) { + case V2TXLivePlayStatusPlaying: + self.hasRecvFirstFrame = YES; + [self hiddeLoading]; + V2LogSimple() + break; + case V2TXLivePlayStatusLoading: + [self showLoading:@"加载中..." withDetailText:@"请等待"]; + V2LogSimple() + break; + default: + break; + } } - (void)onPlayoutVolumeUpdate:(id)player @@ -458,25 +485,20 @@ - (void)onWarning:(id)player code:(V2TXLiveCode)code message:(NS V2Log(@"code:%ld msg:%@ extraInfo:%@", (long)code, msg, extraInfo); } -- (void)onPlayBegin:(id)player { - [self hiddeLoading]; - V2LogSimple() +- (void)onSnapshotComplete:(id)player image:(TXImage *)image { + if (!image) { + [self showText:@"获取截图失败"]; + } else { + [PhotoUtil saveDataToAlbum:UIImagePNGRepresentation(image) completion:^(BOOL success, NSError * _Nullable error) { + if (success) { + [self showText:@"截图已保存到相册"]; + } else { + [self showText:@"截图保存失败"]; + } + }]; + } } -- (void)onLoading:(id)player { - [self showLoading:@"加载中..." withDetailText:@"请等待"]; - V2LogSimple() -} - -- (void)onConnectionBroken:(id)player - reason:(NSInteger)reason { - V2Log(@"reason:%ld", (long)reason); - dispatch_async(dispatch_get_main_queue(), ^{ - [self showText:@"连接断开" withDetailText:nil]; - [self startPlayInner:NO]; - [self hiddeLoading]; - }); -} #pragma mark - UIGestureRecognizerDelegate @@ -487,4 +509,19 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceive return YES; } +#pragma mark - Util + +- (void)showText:(NSString *)text { + dispatch_async(dispatch_get_main_queue(), ^{ + MBProgressHUD *hud = [MBProgressHUD HUDForView:[UIApplication sharedApplication].delegate.window]; + if (hud == nil) { + hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].delegate.window animated:NO]; + } + hud.mode = MBProgressHUDModeText; + hud.label.text = text; + [hud showAnimated:YES]; + [hud hideAnimated:YES afterDelay:1]; + }); +} + @end diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PusherViewController.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PusherViewController.m index ba0b9cd5..ffd4905f 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PusherViewController.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2PusherViewController.m @@ -15,6 +15,7 @@ #import "V2LiveUtils.h" #import "V2QRGenerateViewController.h" #import "MBProgressHUD.h" +#import "PhotoUtil.h" #define V2LogSimple() \ NSLog(@"[%@ %p %s %d]", NSStringFromClass(self.class), self, __func__, __LINE__); @@ -368,13 +369,27 @@ - (void)onStatisticsUpdate:(V2TXLivePusherStatistics *)statistics { // V2Log(@"statistics:%@", statistics) } -- (void)onConnectionStateUpdate:(V2TXLiveConnectionState)state message:(NSString *)msg extraInfo:(NSDictionary *)extraInfo { - if (state == V2TXLiveConnectionStateDisconnected && self.settingContainer.isStart) { +- (void)onPushStatusUpdate:(V2TXLivePushStatus)state message:(NSString *)msg extraInfo:(NSDictionary *)extraInfo { + if (state == V2TXLivePushStatusDisconnected && self.settingContainer.isStart) { [self showText:@"连接已断开" withDetailText:nil]; [self stopPush]; } } +-(void)onSnapshotComplete:(TXImage *)image { + if (!image) { + [self showText:@"获取截图失败"]; + } else { + [PhotoUtil saveDataToAlbum:UIImagePNGRepresentation(image) completion:^(BOOL success, NSError * _Nullable error) { + if (success) { + [self showText:@"截图已保存到相册"]; + } else { + [self showText:@"截图保存失败"]; + } + }]; + } +} + #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { @@ -384,5 +399,20 @@ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceive return YES; } +#pragma mark - Util + +- (void)showText:(NSString *)text { + dispatch_async(dispatch_get_main_queue(), ^{ + MBProgressHUD *hud = [MBProgressHUD HUDForView:[UIApplication sharedApplication].delegate.window]; + if (hud == nil) { + hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].delegate.window animated:NO]; + } + hud.mode = MBProgressHUDModeText; + hud.label.text = text; + [hud showAnimated:YES]; + [hud hideAnimated:YES afterDelay:1]; + }); +} + @end diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PlayerSettingViewController.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PlayerSettingViewController.m index ca3396ce..8ea57a5f 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PlayerSettingViewController.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PlayerSettingViewController.m @@ -15,7 +15,7 @@ #import "V2TXLiveDef.h" #import "MBProgressHUD.h" -@interface V2PlayerSettingViewController () +@interface V2PlayerSettingViewController () @property (nonatomic, weak) UIViewController *hostVC; @property (nonatomic, strong) V2SettingBottomBar *settingBar; @@ -213,7 +213,7 @@ - (void)onClickFeatureSettingsButton { } }], [[V2SettingsButtonItem alloc] initWithTitle:@"视频截图" buttonTitle:@"截图" action:^{ - [wSelf.player snapshot:wSelf]; + [wSelf.player snapshot]; }], ].mutableCopy; } @@ -228,29 +228,6 @@ - (void)onClickStartSettingsButton { } } -#pragma mark - snapshot - -- (void)onSnapshotComplete:(TXImage *)image { - if ([NSThread isMainThread]) { - [self handleSnapshot:image]; - } else { - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleSnapshot:image]; - }); - } -} - -- (void)handleSnapshot:(TXImage *)image { - if (image == nil) { - [self showText:@"获取截图失败"]; - return; - } - UIActivityViewController *vc = [[UIActivityViewController alloc] - initWithActivityItems:@[image] - applicationActivities:nil]; - [self.settingsVC presentViewController:vc animated:YES completion:nil]; -} - #pragma mark - Settings ViewController Embeding - (void)toggleEmbedVC:(UIViewController *)vc { diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PusherSettingViewController.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PusherSettingViewController.m index c695b539..8846d734 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PusherSettingViewController.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2PusherSettingViewController.m @@ -439,34 +439,14 @@ - (void)onEnableRemoteMirror:(BOOL)isOn { - (void)onEnableWatermark:(BOOL)isOn { if (isOn) { UIImage *image = [UIImage imageNamed:@"watermark"]; - [self.pusherVM setWaterMark:image inRect:CGRectMake(40, 60, 60, 30)]; + [self.pusherVM setWaterMark:image inRect:CGRectMake(0.1, 0.15, 120, 30)]; } else { [self.pusherVM setWaterMark:nil inRect:CGRectZero]; } } - (void)snapshotLocalVideo { - __weak __typeof(self) weakSelf = self; - [self.pusherVM snapshot:^(TXImage * _Nonnull image) { - __strong __typeof(weakSelf) self = weakSelf; - if (self == nil) { - return; - } - - [self shareImage:image]; - }]; -} - -- (void)shareImage:(UIImage *)image { - if (image == nil) { - [self showText:@"获取截图失败"]; - return; - } - - UIActivityViewController *vc = [[UIActivityViewController alloc] - initWithActivityItems:@[image] - applicationActivities:nil]; - [self.videoVC presentViewController:vc animated:YES completion:nil]; + [self.pusherVM snapshot]; } #pragma mark - Settings ViewController Embeding @@ -506,17 +486,4 @@ - (void)unembedChildVC:(UIViewController * _Nullable)vc { self.centerContainerView.hidden = YES; } -#pragma mark - Util - -- (void)showText:(NSString *)text { - MBProgressHUD *hud = [MBProgressHUD HUDForView:[UIApplication sharedApplication].delegate.window]; - if (hud == nil) { - hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].delegate.window animated:NO]; - } - hud.mode = MBProgressHUDModeText; - hud.label.text = text; - [hud showAnimated:YES]; - [hud hideAnimated:YES afterDelay:1]; -} - @end diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.h b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.h index 758f8f45..907195ef 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.h +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.h @@ -74,7 +74,7 @@ typedef NS_ENUM(NSInteger, TRTCAudioRoute) { /// 宽度为540 * 0.2 = 108, 高度自动计算 - (void)setWaterMark:(UIImage * _Nullable)image inRect:(CGRect)rect; -- (void)snapshot:(void (^)(TXImage *image))completionBlock; +- (void)snapshot; + (NSArray *)resolutions; + (NSArray *)resolutionNames; diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.m index afb587da..f9e6cbf4 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoNew/V2Setting/V2SettingModel/V2PusherSettingModel.m @@ -1,6 +1,5 @@ #import "V2PusherSettingModel.h" -typedef void (^SnapshotCompletionBlock)(TXImage *); static NSString *const kVideoConfig = @"V2TRTCVideoConfig"; static NSString *const kAudioConfig = @"V2TRTCAudioConfig"; @@ -18,9 +17,8 @@ - (instancetype)initWithMin:(NSInteger)min max:(NSInteger)max defaultBitrate:(NS @end -@interface V2PusherSettingModel() +@interface V2PusherSettingModel() -@property (nonatomic, copy) SnapshotCompletionBlock snapshotBlock; @property (nonatomic, strong) UIImage *waterMarkImg; @property (nonatomic, assign) CGRect waterMarkRect; @@ -97,16 +95,15 @@ - (void)setWaterMark:(UIImage *)image inRect:(CGRect)rect { self.waterMarkImg = image; self.waterMarkRect = rect; if (image == nil) { - [self.pusher setWatermark:nil position:CGPointZero scale:0.0]; + [self.pusher setWatermark:nil x:0.0 y:0.0 scale:0.0]; } else { CGFloat scale = rect.size.width/image.size.width; - [self.pusher setWatermark:image position:rect.origin scale:scale]; + [self.pusher setWatermark:image x:rect.origin.x y:rect.origin.y scale:scale]; } } -- (void)snapshot:(void (^)(TXImage *image))completionBlock { - self.snapshotBlock = completionBlock; - [self.pusher snapshot:self]; +- (void)snapshot { + [self.pusher snapshot]; } + (NSArray *)resolutions { @@ -308,23 +305,4 @@ - (void)applyAudioConfig { [self setIsAudioMuted:self.isAudioMuted]; } -#pragma mark - V2TXLiveSnapshotObserver - -- (void)onSnapshotComplete:(TXImage *)image { - if ([NSThread isMainThread]) { - [self handleSnapshot:image]; - } else { - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleSnapshot:image]; - }); - } -} - -- (void)handleSnapshot:(TXImage *)image { - if (self.snapshotBlock) { - self.snapshotBlock(image); - } - self.snapshotBlock = nil; -} - @end diff --git a/Demo/TXLiteAVDemo/LiveLinkMicDemoOld/LiveRoomUI/LiveRoomPusherViewController.m b/Demo/TXLiteAVDemo/LiveLinkMicDemoOld/LiveRoomUI/LiveRoomPusherViewController.m index e82acf4d..fc6abc74 100644 --- a/Demo/TXLiteAVDemo/LiveLinkMicDemoOld/LiveRoomUI/LiveRoomPusherViewController.m +++ b/Demo/TXLiteAVDemo/LiveLinkMicDemoOld/LiveRoomUI/LiveRoomPusherViewController.m @@ -653,6 +653,11 @@ - (void)onRequestJoinAnchor:(MLVBAnchorInfo *)anchor reason:(NSString *)reason { return; } + if (_playerViewDic.count >= 3) { + [_liveRoom responseJoinAnchor:userID agree:NO reason:@"当前连麦人数已满"]; + return; + } + _hasPendingRequest = YES; dispatch_async(dispatch_get_main_queue(), ^{ NSString *msg = [NSString stringWithFormat:@"[%@]请求连麦", userName]; diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalon.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalon.m new file mode 100644 index 00000000..01db7507 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalon.m @@ -0,0 +1,1197 @@ +// +// TRTCChatSalon.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "TRTCChatSalon.h" +#import "ChatSalonTRTCService.h" +#import "TXChatSalonService.h" +#import "TXChatSalonCommonDef.h" +#import "TRTCCloud.h" + +@interface TRTCChatSalon () + +@property (nonatomic, assign) int mSDKAppID; + +@property (nonatomic, strong) NSString *userID; +@property (nonatomic, strong) NSString *userSig; +@property (nonatomic, strong) NSString *roomID; +@property (nonatomic, strong) NSMutableSet *anchorSeatList; +@property (nonatomic, strong) NSMutableSet *audienceList; +@property (nonatomic, strong) NSMutableDictionary *seatInfoList; +@property (nonatomic, assign) BOOL isTakeSeat; + +@property (nonatomic, strong) ChatSalonInfo *roomInfo; + +@property (nonatomic, weak) id delegate; + +@property (nonatomic, copy, nullable) ActionCallback enterSeatCallback; +@property (nonatomic, copy, nullable) ActionCallback leaveSeatCallback; +@property (nonatomic, copy, nullable) ActionCallback pickSeatCallback; +@property (nonatomic, copy, nullable) ActionCallback kickSeatCallback; + +@property (nonatomic, weak)dispatch_queue_t delegateQueue; + +@property (nonatomic, readonly)TXChatSalonService *roomService; +@property (nonatomic, readonly)ChatSalonTRTCService *roomTRTCService; + +@end + +@implementation TRTCChatSalon + +static TRTCChatSalon *_instance; +static dispatch_once_t onceToken; + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.delegateQueue = dispatch_get_main_queue(); + self.seatInfoList = [[NSMutableDictionary alloc] initWithCapacity:2]; + self.anchorSeatList = [[NSMutableSet alloc] initWithCapacity:2]; + self.audienceList = [[NSMutableSet alloc] initWithCapacity:2]; + self.isTakeSeat = NO; + self.roomService.delegate = self; + self.roomTRTCService.delegate =self; + } + return self; +} + +- (TXChatSalonService *)roomService { + return [TXChatSalonService sharedInstance]; +} + +- (ChatSalonTRTCService *)roomTRTCService { + return [ChatSalonTRTCService sharedInstance]; +} + +- (BOOL)canDelegateResponseMethod:(SEL)method { + return self.delegate && [self.delegate respondsToSelector:method]; +} + +#pragma mark - private method +- (BOOL)isOnSeatWithUserId:(NSString *)userID { + if (self.seatInfoList.count == 0) { + return NO; + } + return [self.seatInfoList.allKeys containsObject:userID]; +} + +- (void)runMainQueue:(void(^)(void))action { + dispatch_async(dispatch_get_main_queue(), ^{ + action(); + }); +} + +- (void)runOnDelegateQueue:(void(^)(void))action { + if (self.delegateQueue) { + dispatch_async(self.delegateQueue, ^{ + action(); + }); + } +} + +- (void)destroy { + [self.roomService destroy]; +} + +- (void)clearList { + [self.seatInfoList removeAllObjects]; + [self.anchorSeatList removeAllObjects]; + [self.audienceList removeAllObjects]; +} + +- (void)exitRoomInternal:(ActionCallback _Nullable)callback { + @weakify(self) + [self.roomTRTCService exitRoom:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code != 0) { + [self runOnDelegateQueue:^{ + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:code message:message]; + } + }]; + } + }]; + TRTCLog(@"start exit room service"); + [self.roomService exitRoom:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; + [self clearList]; + self.roomID = @""; +} + +- (void)getAudienceList:(ChatSalonUserListCallback _Nullable)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService getAudienceList:^(int code, NSString * _Nonnull message, NSArray * _Nonnull userInfos) { + TRTCLog(@"get audience list finish, code:%d, message:%@, userListCount:%d", code, message, userInfos.count); + NSMutableArray *userInfoList = [[NSMutableArray alloc] initWithCapacity:2]; + for (TXChatSalonUserInfo* info in userInfos) { + ChatSalonUserInfo* userInfo = [[ChatSalonUserInfo alloc] init]; + userInfo.userID = info.userID; + userInfo.userName = info.userName; + userInfo.userAvatar = info.avatarURL; + [userInfoList addObject:userInfo]; + } + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message, userInfoList); + }]; + } + }]; + }]; +} + +- (void)enterTRTCRoomInnerWithRoomId:(NSString *)roomId userID:(NSString *)userID userSign:(NSString *)userSig role:(NSInteger)role callback:(ActionCallback)callback { + TRTCLog(@"start enter trtc room."); + @weakify(self) + [self.roomTRTCService enterRoomWithSdkAppId:self.mSDKAppID roomId:roomId userID:userID userSign:userSig role:role callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; +} + +#pragma mark - TRTCChatSalon 实现 ++ (instancetype)sharedInstance { + dispatch_once(&onceToken, ^{ + _instance = [[TRTCChatSalon alloc] init]; + [TXChatSalonService sharedInstance].delegate = _instance; + [ChatSalonTRTCService sharedInstance].delegate = _instance; + }); + return _instance; +} + ++ (void)destroySharedInstance { + onceToken = 0; + _instance = nil; +} + +- (void)setDelegate:(id)delegate{ + self->_delegate = delegate; +} + +- (void)setDelegateQueue:(dispatch_queue_t)queue { + self->_delegateQueue = queue; +} + +- (void)login:(int)sdkAppID userID:(NSString *)userID userSig:(NSString *)userSig callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + if (sdkAppID != 0 && userID && ![userID isEqualToString:@""] && userSig && ![userSig isEqualToString:@""]) { + self.mSDKAppID = sdkAppID; + self.userID = userID; + self.userSig = userSig; + TRTCLog(@"start login room service"); + [self.roomService loginWithSdkAppId:sdkAppID userID:userID userSig:userSig callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self.roomService getSelfInfo]; + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; + } else { + TRTCLog(@"start login failed. params invalid."); + callback(-1, @"start login failed. params invalid."); + } + }]; +} + +- (void)logout:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"start logout"); + self.mSDKAppID = 0; + self.userID = @""; + self.userSig = @""; + TRTCLog(@"start logout room service"); + [self.roomService logout:^(int code, NSString * _Nonnull message) { + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; + }]; +} + +- (void)setSelfProfile:(NSString *)userName avatarURL:(NSString *)avatarURL callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService setSelfProfileWithUserName:userName avatarUrl:avatarURL callback:^(int code, NSString * _Nonnull message) { + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; + }]; +} + +- (void)createRoom:(int)roomID roomParam:(ChatSalonParam *)roomParam callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService getSelfInfo]; + if (roomID == 0) { + TRTCLog(@"crate room fail. params invalid."); + if (callback) { + callback(-1, @"create room fail. parms invalid."); + } + return; + } + self.roomID = [NSString stringWithFormat:@"%d", roomID]; + [self clearList]; + NSString* roomName = roomParam.roomName; + NSString* roomCover = roomParam.coverUrl; + BOOL isNeedrequest = roomParam.needRequest; + [self.roomService createRoomWithRoomId:self.roomID + roomName:roomName + coverUrl:roomCover + needRequest:isNeedrequest + callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code == 0) { + [self enterTRTCRoomInnerWithRoomId:self.roomID userID:self.userID userSign:self.userSig role:kTRTCRoleAnchorValue callback:callback]; + return; + } else { + [self runOnDelegateQueue:^{ + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:code message:message]; + } + }]; + } + if (callback) { + callback(code, message); + } + }]; + }]; +} + +- (void)destroyRoom:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"start destroyu room."); + [self.roomTRTCService exitRoom:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code != 0) { + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:code message:message]; + } + } + }]; + [self.roomService exitRoom:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code != 0) { + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:code message:message]; + } + } + }]; + [self.roomService destroyRoom:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"destroy room finish, code:%d, message: %@", code, message); + if (callback) { + [self runOnDelegateQueue:^{ + callback(code, message); + }]; + } + }]; + [self clearList]; + }]; +} + +- (void)enterRoom:(NSInteger)roomID callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self clearList]; + self.roomID = [NSString stringWithFormat:@"%ld", (long)roomID]; + TRTCLog(@"start enter room, room id is %ld", (long)roomID); + [self enterTRTCRoomInnerWithRoomId:self.roomID userID:self.userID userSign:self.userSig role:kTRTCRoleAudienceValue callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (callback) { + [self runMainQueue:^{ + callback(code, message); + }]; + } + }]; + [self.roomService enterRoom:self.roomID callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code != 0) { + [self runOnDelegateQueue:^{ + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:code message:message]; + } + }]; + } + }]; + }]; +} + +- (void)exitRoom:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"start exit room"); + if ([self isOnSeatWithUserId:self.userID]) { + [self leaveSeat:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self exitRoomInternal:callback]; + }]; + } else { + [self exitRoomInternal:callback]; + } + }]; +} + +- (void)getRoomInfoList:(NSArray *)roomIdList callback:(ChatSalonInfoCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"start get room info:%@", roomIdList); + NSMutableArray* roomIds = [[NSMutableArray alloc] initWithCapacity:2]; + for (NSNumber *roomId in roomIdList) { + [roomIds addObject:[roomId stringValue]]; + } + [self.roomService getRoomInfoList:roomIds calback:^(int code, NSString * _Nonnull message, NSArray * _Nonnull roomInfos) { + if (code == 0) { + TRTCLog(@"roomInfos: %@", roomInfos); + NSMutableArray* trtcRoomInfos = [[NSMutableArray alloc] initWithCapacity:2]; + for (TXChatSalonRoomInfo *info in roomInfos) { + if ([info.roomId integerValue] != 0) { + ChatSalonInfo *roomInfo = [[ChatSalonInfo alloc] init]; + roomInfo.roomID = [info.roomId integerValue]; + roomInfo.ownerId = info.ownerId; + roomInfo.memberCount = info.memberCount; + roomInfo.roomName = info.roomName; + roomInfo.coverUrl = info.cover; + roomInfo.ownerName = info.ownerName; + roomInfo.needRequest = info.needRequest == 1; + [trtcRoomInfos addObject:roomInfo]; + } + } + if (callback) { + callback(code, message, trtcRoomInfos); + } + } else { + if (callback) { + callback(code, message, @[]); + } + } + }]; + }]; +} + +- (void)getUserInfoList:(NSArray *)userIDList callback:(ChatSalonUserListCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + if (!userIDList) { + [self getAudienceList:callback]; + return; + } + [self.roomService getUserInfo:userIDList callback:^(int code, NSString * _Nonnull message, NSArray * _Nonnull userInfos) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + NSMutableArray* userList = [[NSMutableArray alloc] initWithCapacity:2]; + [userInfos enumerateObjectsUsingBlock:^(TXChatSalonUserInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + ChatSalonUserInfo* userInfo = [[ChatSalonUserInfo alloc] init]; + userInfo.userID = obj.userID; + userInfo.userName = obj.userName; + userInfo.userAvatar = obj.avatarURL; + [userList addObject:userInfo]; + }]; + if (callback) { + callback(code, message, userList); + } + }]; + }]; + }]; +} + +- (void)enterSeat:(ActionCallback _Nullable)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self isOnSeatWithUserId:self.userID]) { + [self runOnDelegateQueue:^{ + if (callback) { + callback(-1, @"you are alread in the seat."); + } + }]; + return; + } + self.enterSeatCallback = callback; + [self.roomService takeSeat:^(int code, NSString * _Nonnull message) { + if (code == 0) { + TRTCLog(@"take seat callback success, and wait attrs changed"); + callback(0, @"take seat callback success, and wait attrs changed"); + } else { + self.enterSeatCallback = nil; + self.isTakeSeat = NO; + if (callback) { + callback(code, message); + } + } + }]; + }]; +} + +- (void)leaveSeat:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + if (!self.isTakeSeat) { + [self runOnDelegateQueue:^{ + callback(-1, @"you are not in the seat."); + }]; + return; + } + self.leaveSeatCallback = callback; + [self.roomService leaveSeat:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code == 0) { + TRTCLog(@"levae seat success. and wait attrs changed"); + } else { + self.leaveSeatCallback = nil; + if (callback) { + callback(code, message); + } + } + }]; + }]; +} + +- (void)pickSeat:(NSString *)userID callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self isOnSeatWithUserId:userID]) { + [self runOnDelegateQueue:^{ + if (callback) { + callback(-1, @"该用户已经是上麦主播了"); + } + }]; + return; + } + self.pickSeatCallback = callback; + [self.roomService pickSeat:userID callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code == 0) { + TRTCLog(@"pick seat calback success. and wait attrs changed."); + } else { + self.pickSeatCallback = nil; + if (callback) { + callback(code, message); + } + } + }]; + }]; +} + +- (void)kickSeat:(NSString *)userID callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + self.kickSeatCallback = callback; + [self.roomService kickSeat:userID callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + if (code == 0) { + TRTCLog(@"kick seat calback success. and wait attrs changed."); + } else { + self.kickSeatCallback = nil; + if (callback) { + callback(code, message); + } + } + }]; + }]; +} + +- (void)muteSeat:(NSString *)userID isMute:(BOOL)isMute callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService muteSeat:userID mute:isMute callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +- (void)startMicrophone { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService startMicrophone]; + }]; +} + +- (void)stopMicrophone{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService stopMicrophone]; + }]; +} + +- (void)setAuidoQuality:(NSInteger)quality { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService setAudioQuality:quality]; + }]; +} + +- (void)muteLocalAudio:(BOOL)mute{ + @weakify(self) + [self muteSeat:self.userID isMute:mute callback:nil]; + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService muteLocalAudio:mute]; + }]; +} + +- (void)setSpeaker:(BOOL)userSpeaker { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService setSpeaker:userSpeaker]; + }]; +} + +- (void)setAudioCaptureVolume:(NSInteger)voluem { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService setAudioCaptureVolume:voluem]; + }]; +} + +- (void)setAudioPlayoutVolume:(NSInteger)volume { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService setAudioPlayoutVolume:volume]; + }]; +} + +- (void)muteRemoteAudio:(NSString *)userID mute:(BOOL)mute{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService muteRemoteAudioWithUserId:userID isMute:mute]; + }]; +} + +- (void)muteAllRemoteAudio:(BOOL)isMute{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomTRTCService muteAllRemoteAudio:isMute]; + }]; +} + +- (TXAudioEffectManager *)getAudioEffectManager{ + return [[TRTCCloud sharedInstance] getAudioEffectManager]; +} + +- (void)sendRoomTextMsg:(NSString *)message callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService sendRoomTextMsg:message callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +- (void)sendRoomCustomMsg:(NSString *)cmd message:(NSString *)message callback:(ActionCallback)callback { + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService sendRoomCustomMsg:cmd message:message callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +- (NSString *)sendInvitation:(NSString *)cmd userID:(NSString *)userID content:(NSString *)content callback:(ActionCallback)callback{ + @weakify(self) + return [self.roomService sendInvitation:cmd userID:userID content:content callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; +} + +- (void)acceptInvitation:(NSString *)identifier callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService acceptInvitation:identifier callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +- (void)rejectInvitation:(NSString *)identifier callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService rejectInvitaiton:identifier callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +- (void)cancelInvitation:(NSString *)identifier callback:(ActionCallback)callback{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self.roomService cancelInvitation:identifier callback:^(int code, NSString * _Nonnull message) { + @strongify(self) + if (!self) { + return; + } + [self runOnDelegateQueue:^{ + if (callback) { + callback(code, message); + } + }]; + }]; + }]; +} + +#pragma mark - ChatSalonTRTCServiceDelegate + +- (void)onTRTCAnchorEnter:(NSString *)userID { + [self.anchorSeatList addObject:userID]; +} + +- (void)onTRTCAnchorExit:(NSString *)userID { + if (self.roomService.isOwner) { + if (self.seatInfoList.count > 0) { + if ([self.seatInfoList.allKeys containsObject:userID]) { + [self kickSeat:userID callback:nil]; + } + } + } +} + +- (void)onTRTCAudioAvailable:(NSString *)userID available:(BOOL)available { + +} + +- (void)onError:(NSInteger)code message:(NSString *)message { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:(int)code message:message]; + } + }]; +} + +- (void)onNetWorkQuality:(TRTCQualityInfo *)trtcQuality arrayList:(NSArray *)arrayList { + +} + +- (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onUserVolumeUpdate:totalVolume:)]) { + [self.delegate onUserVolumeUpdate:userVolumes totalVolume:totalVolume]; + } + }]; +} + +#pragma mark - ITXRoomServiceDelegate +- (void)onRoomDestroyWithRoomId:(NSString *)roomID{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + [self exitRoom:nil]; + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onRoomDestroy:)]) { + [self.delegate onRoomDestroy:roomID]; + } + }]; + }]; +} + +- (void)onRoomRecvRoomTextMsg:(NSString *)roomID message:(NSString *)message userInfo:(TXChatSalonUserInfo *)userInfo { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onRecvRoomTextMsg:userInfo:)]) { + [self.delegate onRecvRoomTextMsg:message userInfo:user]; + } + }]; +} + +- (void)onRoomRecvRoomCustomMsg:(NSString *)roomID cmd:(NSString *)cmd message:(NSString *)message userInfo:(TXChatSalonUserInfo *)userInfo { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onRecvRoomCustomMsg:message:userInfo:)]) { + [self.delegate onRecvRoomCustomMsg:cmd message:message userInfo:user]; + } + }]; +} + +- (void)onRoomInfoChange:(TXChatSalonRoomInfo *)roomInfo{ + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([roomInfo.roomId intValue] == 0) { + return; + } + ChatSalonInfo *room = [[ChatSalonInfo alloc] init]; + room.roomID = [roomInfo.roomId intValue]; + room.ownerId = roomInfo.ownerId; + room.memberCount = roomInfo.memberCount; + room.ownerName = roomInfo.ownerName; + room.coverUrl = roomInfo.cover; + room.needRequest = roomInfo.needRequest == 1; + room.roomName = roomInfo.roomName; + if ([self canDelegateResponseMethod:@selector(onRoomInfoChange:)]) { + [self.delegate onRoomInfoChange:room]; + } + }]; +} + +- (void)onSeatInfoListChange:(NSDictionary *)seatInfoList{ + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + NSMutableDictionary* roomSeatList = [[NSMutableDictionary alloc] initWithCapacity:2]; + for (TXChatSalonSeatInfo* info in seatInfoList.allValues) { + ChatSalonSeatInfo* seat = [[ChatSalonSeatInfo alloc] init]; + seat.userID = info.user; + seat.mute = info.mute; + [roomSeatList setObject:seat forKey:seat.userID]; + } + self.seatInfoList = [roomSeatList mutableCopy]; + if ([self canDelegateResponseMethod:@selector(onEnterRoomSeatListNotify:)]) { + [self.delegate onEnterRoomSeatListNotify:[roomSeatList allValues]]; + } + }]; +} + +- (void)onRoomAudienceEnter:(TXChatSalonUserInfo *)userInfo { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onAudienceEnter:)]) { + [self.delegate onAudienceEnter:user]; + } + }]; +} + +- (void)onRoomAudienceLeave:(TXChatSalonUserInfo *)userInfo { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onAudienceExit:)]) { + [self.delegate onAudienceExit:user]; + } + }]; +} + +- (void)onSeatTakeWithUserInfo:(TXChatSalonUserInfo *)userInfo{ + @weakify(self) + [self runMainQueue:^{ + @strongify(self) + if (!self) { + return; + } + BOOL isSelfEnterSeat = [userInfo.userID isEqualToString:self.userID]; + if (isSelfEnterSeat) { + // 是自己上线了 + self.isTakeSeat = YES; + [self.roomTRTCService switchToAnchor]; + BOOL mute = self.seatInfoList[userInfo.userID].mute; + [self.roomTRTCService muteLocalAudio:mute]; + } + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onAnchorEnterSeat:)]) { + [self.delegate onAnchorEnterSeat:user]; + } + if (self.pickSeatCallback) { + self.pickSeatCallback(0, @"pick seat success"); + self.pickSeatCallback = nil; + } + }]; + if (isSelfEnterSeat) { + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if (self.enterSeatCallback) { + self.enterSeatCallback(0, @"enter seat success."); + self.enterSeatCallback = nil; + } + }]; + } + }]; +} + +- (void)onSeatLeaveWithUserInfo:(TXChatSalonUserInfo *)userInfo { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self.userID isEqualToString:userInfo.userID]) { + self.isTakeSeat = NO; + [self.roomTRTCService switchToAudience]; + } + ChatSalonUserInfo* user = [[ChatSalonUserInfo alloc] init]; + user.userID = userInfo.userID; + user.userName = userInfo.userName; + user.userAvatar = userInfo.avatarURL; + if ([self canDelegateResponseMethod:@selector(onAnchorLeaveSeat:)]) { + [self.delegate onAnchorLeaveSeat:user]; + } + if (self.kickSeatCallback) { + self.kickSeatCallback(0, @"kick seat success."); + self.kickSeatCallback = nil; + } + if ([self.userID isEqualToString:userInfo.userID]) { + if (self.leaveSeatCallback) { + self.leaveSeatCallback(0, @"leave seat success."); + self.leaveSeatCallback = nil; + } + } + }]; +} + +- (void)onSeatMuteWithUser:(NSString *)userID mute:(BOOL)isMute { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if (self.isTakeSeat && [userID isEqualToString:self.userID]) { + [self.roomTRTCService muteLocalAudio:isMute]; + } + if ([self canDelegateResponseMethod:@selector(onSeatMute:isMute:)]) { + [self.delegate onSeatMute:userID isMute:isMute]; + } + }]; +} + +- (void)onReceiveNewInvitationWithIdentifier:(NSString *)identifier inviter:(NSString *)inviter cmd:(NSString *)cmd content:(NSString *)content{ + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onReceiveNewInvitation:inviter:cmd:content:)]) { + [self.delegate onReceiveNewInvitation:identifier inviter:inviter cmd:cmd content:content]; + } + }]; +} + +- (void)onInviteeAcceptedWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onInviteeAccepted:invitee:)]) { + [self.delegate onInviteeAccepted:identifier invitee:invitee]; + } + }]; +} + +- (void)onInviteeRejectedWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onInviteeRejected:invitee:)]) { + [self.delegate onInviteeRejected:identifier invitee:invitee]; + } + }]; +} + +- (void)onInviteeCancelledWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee { + @weakify(self) + [self runOnDelegateQueue:^{ + @strongify(self) + if (!self) { + return; + } + if ([self canDelegateResponseMethod:@selector(onInvitationCancelled:invitee:)]) { + [self.delegate onInvitationCancelled:identifier invitee:invitee]; + } + }]; +} + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalonDef.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalonDef.m new file mode 100644 index 00000000..13f1165f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/TRTCChatSalonDef.m @@ -0,0 +1,63 @@ +// +// TRTCChatSalonDef.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "TRTCChatSalonDef.h" + +@implementation ChatSalonParam + +@end + +@implementation ChatSalonSeatInfo + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.mute = NO; + self.userID = @""; + } + return self; +} + +-(NSString *)description { + return [NSString stringWithFormat:@"SeatInfo user: %@", self.userID]; +} + +@end + +@implementation ChatSalonUserInfo + +- (void)setUserName:(NSString *)userName{ + if (!userName) { + userName = @""; + } + _userName = userName; +} + +- (void)setUserAvatar:(NSString *)userAvatar{ + if (!userAvatar) { + userAvatar = @""; + } + _userAvatar = userAvatar; +} + +@end + +@implementation ChatSalonInfo + +-(instancetype)initWithRoomID:(NSInteger)roomID ownerId:(NSString *)ownerId memberCount:(NSInteger)memberCount { + self = [super init]; + if (self) { + self.roomID = roomID; + self.ownerId = ownerId; + self.memberCount = memberCount; + } + return self; +} + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.h new file mode 100644 index 00000000..23951c69 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.h @@ -0,0 +1,69 @@ +// +// TXChatSalonBaseDef.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +#ifdef DEBUG +#define TRTCLog(fmt, ...) NSLog((@"TRTC LOG:%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__) +#else +#define TRTCLog(...) +#endif + +@class TXChatSalonUserInfo; +@class TXChatSalonRoomInfo; + +typedef void(^TXCallback)(int code, NSString *message); +typedef void(^TXUserListCallback)(int code, NSString *message, NSArray *userInfos); +typedef void(^TXChatSalonRoomInfoListCallback)(int code, NSString *message, NSArray *roomInfos); + +typedef NS_ENUM(NSUInteger, TXSeatStatus) { + kTXSeatStatusUnused = 0, + kTXSeatStatusUsed = 1, + kTXSeatStatusClose = 2, +}; + +@interface TXChatSalonRoomInfo : NSObject + +@property (nonatomic, strong) NSString *roomId; +@property (nonatomic, assign) UInt32 memberCount; + +@property (nonatomic, strong) NSString *ownerId; +@property (nonatomic, strong) NSString *ownerName; +@property (nonatomic, strong) NSString *roomName; +@property (nonatomic, strong) NSString *cover; +@property (nonatomic, assign) NSInteger seatSize; +@property (nonatomic, assign) NSInteger needRequest; + +@end + +@interface TXChatSalonUserInfo : NSObject + +@property (nonatomic, strong) NSString *userID; +@property (nonatomic, strong) NSString *userName; +@property (nonatomic, strong) NSString *avatarURL; + +@end + +@interface TXChatSalonSeatInfo : NSObject + +@property (nonatomic, assign) BOOL mute; +@property (nonatomic, strong) NSString *user; + +@end + +@interface TXChatSalonInviteData : NSObject + +@property (nonatomic, strong) NSString *roomId; +@property (nonatomic, strong) NSString *command; +@property (nonatomic, strong) NSString *message; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.m new file mode 100644 index 00000000..1ee57308 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonBaseDef.m @@ -0,0 +1,37 @@ +// +// TXChatSalonBaseDef.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "TXChatSalonBaseDef.h" + +@implementation TXChatSalonRoomInfo + +@end + +@implementation TXChatSalonUserInfo + + +@end + +@implementation TXChatSalonSeatInfo + +- (instancetype)init +{ + self = [super init]; + if (self) { + self.mute = NO; + self.user = @""; + } + return self; +} + +@end + +@implementation TXChatSalonInviteData + + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonCommonDef.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonCommonDef.h new file mode 100644 index 00000000..f5aed26f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/base/TXChatSalonCommonDef.h @@ -0,0 +1,55 @@ +// +// TXChatSalonCommonDef.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/3. +// Copyright © 2020 tencent. All rights reserved. +// + +#ifndef TXChatSalonCommonDef_h +#define TXChatSalonCommonDef_h + +/** + Synthsize a weak or strong reference. + + Example: + @weakify(self) + [self doSomething^{ + @strongify(self) + if (!self) return; + ... + }]; + */ +#ifndef weakify + #if DEBUG + #if __has_feature(objc_arc) + #define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object; + #else + #define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object; + #endif + #else + #if __has_feature(objc_arc) + #define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object; + #else + #define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object; + #endif + #endif +#endif + +#ifndef strongify + #if DEBUG + #if __has_feature(objc_arc) + #define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object; + #else + #define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object; + #endif + #else + #if __has_feature(objc_arc) + #define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object; + #else + #define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object; + #endif + #endif +#endif + +#endif /* TXChatSalonCommonDef_h */ diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.h new file mode 100644 index 00000000..dddfc017 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.h @@ -0,0 +1,58 @@ +// +// TXChatSalonIMJsonHandle.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/2. +// Copyright © 2020 tencent. All rights reserved. +// + +#import +#import "TXChatSalonBaseDef.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSString* VOICE_ROOM_KEY_ATTR_VERSION = @"version"; +static NSString* VOICE_ROOM_VALUE_ATTR_VERSION = @"1.0"; +static NSString* VOICE_ROOM_KEY_ROOM_INFO = @"roomInfo"; +static NSString* VOICE_ROOM_KEY_SEAT = @"seat"; + +static NSString* VOICE_ROOM_KEY_CMD_VERSION = @"version"; +static NSString* VOICE_ROOM_VALUE_CMD_VERSION = @"1.0"; +static NSString* VOICE_ROOM_KEY_CMD_ACTION = @"action"; + +static NSString* VOICE_ROOM_KEY_INVITATION_VERSION = @"version"; +static NSString* VOICE_ROOM_VALUE_INVITATION_VERSION = @"1.0"; +static NSString* VOICE_ROOM_KEY_INVITATION_CMD = @"command"; +static NSString* VOICE_ROOM_KEY_INVITAITON_CONTENT = @"content"; + +typedef NS_ENUM(NSUInteger, TXChatSalonCustomCodeType) { + kChatSalonCodeUnknown = 0, + kChatSalonCodeDestroy = 200, + kChatSalonCodeCustomMsg = 301, +}; + +@interface TXChatSalonIMJsonHandle : NSObject + ++ (NSDictionary *)getInitRoomDicWithRoomInfo:(TXChatSalonRoomInfo *)roominfo seatInfoList:(NSDictionary *)seatInfoList; + ++ (NSDictionary *)getSeatInfoListJsonStrWithSeatInfoList:(NSArray *)seatInfoList; + ++ (NSDictionary *)getSeatInfoJsonStrWithUserID:(NSString *)userID info:(TXChatSalonSeatInfo *)info; + ++ (TXChatSalonRoomInfo * _Nullable)getRoomInfoFromAttr:(NSDictionary *)attr; + ++ (NSDictionary * _Nullable)getSeatListFromAttr:(NSDictionary *)attr; + ++ (NSString *)getInvitationMsgWithRoomId:(NSString *)roomId cmd:(NSString *)cmd content:(NSString *)content; + ++ (TXChatSalonInviteData * _Nullable)parseInvitationMsgWithJson:(NSString *)json; + ++ (NSString *)getRoomdestroyMsg; + ++ (NSString *)getCusMsgJsonStrWithCmd:(NSString *)cmd msg:(NSString *)msg; + ++ (NSDictionary *)parseCusMsgWithJsonDic:(NSDictionary *)jsonDic; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.m new file mode 100644 index 00000000..fbd8a748 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonIMJsonHandle.m @@ -0,0 +1,101 @@ +// +// TXChatSalonIMJsonHandle.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/2. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "TXChatSalonIMJsonHandle.h" +#import + +@implementation TXChatSalonIMJsonHandle + ++ (NSDictionary *)getInitRoomDicWithRoomInfo:(TXChatSalonRoomInfo *)roominfo seatInfoList:(NSDictionary *)seatInfoList{ + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + [result setValue:VOICE_ROOM_KEY_ATTR_VERSION forKey:VOICE_ROOM_VALUE_ATTR_VERSION]; + NSString *jsonRoomInfo = [roominfo mj_JSONString]; + [result setValue:jsonRoomInfo forKey:VOICE_ROOM_KEY_ROOM_INFO]; + for (int index = 0; index < seatInfoList.allKeys.count; index += 1) { + NSString *key = [seatInfoList.allKeys objectAtIndex:index]; + NSLog(@"======--- key: %@", key); + NSString *jsonInfo = [seatInfoList[key] mj_JSONString]; + TXChatSalonSeatInfo *info = seatInfoList[key]; + NSString *jsonkey = [NSString stringWithFormat:@"%@%@", VOICE_ROOM_KEY_SEAT, info.user]; + [result setValue:jsonInfo forKey:jsonkey]; + } + return result; +} + ++ (NSDictionary *)getSeatInfoListJsonStrWithSeatInfoList:(NSArray *)seatInfoList { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + [seatInfoList enumerateObjectsUsingBlock:^(TXChatSalonSeatInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + NSString *key = [NSString stringWithFormat:@"%@%@", VOICE_ROOM_KEY_SEAT, obj.user]; + [result setValue:obj forKey:key]; + }]; + return result; +} + ++ (NSDictionary *)getSeatInfoJsonStrWithUserID:(NSString *)userID info:(TXChatSalonSeatInfo *)info { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + NSString *json = [info mj_JSONString]; + NSString *key = [NSString stringWithFormat:@"%@%@", VOICE_ROOM_KEY_SEAT, userID]; + [result setValue:json forKey:key]; + return result; +} + ++ (TXChatSalonRoomInfo *)getRoomInfoFromAttr:(NSDictionary *)attr { + NSString *jsonStr = [attr objectForKey:VOICE_ROOM_KEY_ROOM_INFO]; + return [TXChatSalonRoomInfo mj_objectWithKeyValues:jsonStr]; +} + ++ (NSDictionary *)getSeatListFromAttr:(NSDictionary *)attr { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + [attr enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { + if ([key containsString:VOICE_ROOM_KEY_SEAT]) { + TXChatSalonSeatInfo *seatInfo = [TXChatSalonSeatInfo mj_objectWithKeyValues:obj]; + if (![seatInfo.user isEqualToString:@""]) { + [result setValue:seatInfo forKey:seatInfo.user]; + } + } + }]; + return result; +} + ++ (NSString *)getInvitationMsgWithRoomId:(NSString *)roomId cmd:(NSString *)cmd content:(NSString *)content { + TXChatSalonInviteData *data = [[TXChatSalonInviteData alloc] init]; + data.roomId = roomId; + data.command = cmd; + data.message = content; + NSString *jsonString = [data mj_JSONString]; + return jsonString; +} + ++ (TXChatSalonInviteData *)parseInvitationMsgWithJson:(NSString *)json { + return [TXChatSalonInviteData mj_objectWithKeyValues:json]; +} + ++ (NSString *)getRoomdestroyMsg { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + [result setValue:VOICE_ROOM_VALUE_ATTR_VERSION forKey:VOICE_ROOM_KEY_ATTR_VERSION]; + [result setValue:@(kChatSalonCodeDestroy) forKey:VOICE_ROOM_KEY_CMD_ACTION]; + return [result mj_JSONString]; +} + ++ (NSString *)getCusMsgJsonStrWithCmd:(NSString *)cmd msg:(NSString *)msg { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + [result setValue:VOICE_ROOM_VALUE_ATTR_VERSION forKey:VOICE_ROOM_KEY_ATTR_VERSION]; + [result setValue:@(kChatSalonCodeCustomMsg) forKey:VOICE_ROOM_KEY_CMD_ACTION]; + [result setValue:cmd forKey:VOICE_ROOM_KEY_INVITATION_CMD]; + [result setValue:msg forKey:@"message"]; + return [result mj_JSONString]; +} + ++ (NSDictionary *)parseCusMsgWithJsonDic:(NSDictionary *)jsonDic { + NSMutableDictionary *result = [[NSMutableDictionary alloc] initWithCapacity:2]; + result[@"cmd"] = [jsonDic objectForKey:VOICE_ROOM_KEY_INVITATION_CMD] ?: @""; + result[@"message"] = [jsonDic objectForKey:@"message"] ?: @""; + return result; +} + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.h new file mode 100644 index 00000000..ffb09024 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.h @@ -0,0 +1,96 @@ +// +// TXChatSalonService.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/1. +// Copyright © 2020 tencent. All rights reserved. +// + +#import +#import "TXChatSalonBaseDef.h" + +NS_ASSUME_NONNULL_BEGIN + +@protocol ITXRoomServiceDelegate + +- (void)onRoomDestroyWithRoomId:(NSString *)roomID; +- (void)onRoomRecvRoomTextMsg:(NSString *)roomID message:(NSString *)message userInfo:(TXChatSalonUserInfo *)userInfo; +- (void)onRoomRecvRoomCustomMsg:(NSString *)roomID cmd:(NSString *)cmd message:(NSString *)message userInfo:(TXChatSalonUserInfo *)userInfo; +- (void)onRoomInfoChange:(TXChatSalonRoomInfo *)roomInfo; +- (void)onSeatInfoListChange:(NSDictionary *)seatInfoList; +- (void)onRoomAudienceEnter:(TXChatSalonUserInfo *)userInfo; +- (void)onRoomAudienceLeave:(TXChatSalonUserInfo *)userInfo; +- (void)onSeatTakeWithUserInfo:(TXChatSalonUserInfo *)userInfo; +- (void)onSeatLeaveWithUserInfo:(TXChatSalonUserInfo *)userInfo; +- (void)onSeatMuteWithUser:(NSString *)userID mute:(BOOL)isMute; +- (void)onReceiveNewInvitationWithIdentifier:(NSString *)identifier inviter:(NSString *)inviter cmd:(NSString *)cmd content:(NSString *)content; +- (void)onInviteeAcceptedWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee; +- (void)onInviteeRejectedWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee; +- (void)onInviteeCancelledWithIdentifier:(NSString *)identifier invitee:(NSString *)invitee; + +@end + +static int VOICE_ROOM_SERVICE_CODE_ERROR = -1; + +@interface TXChatSalonService : NSObject + +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign, readonly)BOOL isOwner; + + ++ (instancetype)sharedInstance; + +- (void)loginWithSdkAppId:(int)sdkAppId userID:(NSString *)userID userSig:(NSString *)userSig callback:(TXCallback _Nullable)callback; +- (void)logout:(TXCallback _Nullable)callback; +- (void)getSelfInfo; +- (void)setSelfProfileWithUserName:(NSString *)userName + avatarUrl:(NSString *)avatarUrl + callback:(TXCallback _Nullable)callback; + +- (void)createRoomWithRoomId:(NSString *)roomId + roomName:(NSString *)roomName + coverUrl:(NSString *)coverUrl + needRequest:(BOOL)needRequest + callback:(TXCallback _Nullable)callback; + +- (void)destroyRoom:(TXCallback _Nullable)callback; + +- (void)enterRoom:(NSString *)roomId callback:(TXCallback _Nullable)callback; + +- (void)exitRoom:(TXCallback _Nullable)callback; + +- (void)takeSeat:(TXCallback _Nullable)callback; + +- (void)leaveSeat:(TXCallback _Nullable)callback; + +- (void)pickSeat:(NSString *)userID callback:(TXCallback _Nullable)callback; + +- (void)kickSeat:(NSString *)userID callback:(TXCallback)callback; + +- (void)muteSeat:(NSString *)userID mute:(BOOL)mute callback:(TXCallback)callback; + +- (void)getUserInfo:(NSArray *)userList callback:(TXUserListCallback _Nullable)callback; + +- (void)sendRoomTextMsg:(NSString *)msg callback:(TXCallback _Nullable)callback; + +- (void)sendRoomCustomMsg:(NSString *)cmd message:(NSString *)message callback:(TXCallback _Nullable)callback; + +- (void)sendGroupMsg:(NSString *)message callback:(TXCallback _Nullable)callback; + +- (void)getAudienceList:(TXUserListCallback _Nullable)callback; + +- (void)getRoomInfoList:(NSArray *)roomIds calback:(TXChatSalonRoomInfoListCallback _Nullable)callback; + +- (void)destroy; + +- (NSString *)sendInvitation:(NSString *)cmd userID:(NSString *)userID content:(NSString *)content callback:(TXCallback _Nullable)callback; + +- (void)acceptInvitation:(NSString *)identifier callback:(TXCallback _Nullable)callback; + +- (void)rejectInvitaiton:(NSString *)identifier callback:(TXCallback _Nullable)callback; + +- (void)cancelInvitation:(NSString *)identifier callback:(TXCallback _Nullable)callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.m new file mode 100644 index 00000000..b6dee405 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/chatsalon/TXChatSalonService.m @@ -0,0 +1,980 @@ +// +// TXChatSalonService.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/1. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "TXChatSalonService.h" +#import +#import +#import "TXChatSalonIMJsonHandle.h" +#import "TXChatSalonCommonDef.h" + +@interface TXChatSalonService () + +@property (nonatomic, assign) BOOL isInitIMSDK; +@property (nonatomic, assign) BOOL isLogin; +@property (nonatomic, assign) BOOL isEnterRoom; + +@property (nonatomic, strong) NSString *mRoomId; +@property (nonatomic, strong) NSString *selfUserId; +@property (nonatomic, strong) NSString *ownerUserId; +@property (nonatomic, strong) TXChatSalonRoomInfo *roomInfo; +@property (nonatomic, strong) NSMutableDictionary *seatInfoList; // 懒加载初始化 +@property (nonatomic, strong) NSString *selfUserName; + +@property (nonatomic, strong, readonly)V2TIMManager* imManager; + +@end + +@implementation TXChatSalonService + ++ (instancetype)sharedInstance { + static TXChatSalonService* instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[TXChatSalonService alloc] init]; + }); + return instance; +} + +- (NSMutableDictionary *)seatInfoList { + if (!_seatInfoList) { + _seatInfoList = [[NSMutableDictionary alloc] initWithCapacity:2]; + } + return _seatInfoList; +} + +#pragma mark - public method +- (void)loginWithSdkAppId:(int)sdkAppId + userID:(NSString *)userID + userSig:(NSString *)userSig + callback:(TXCallback)callback { + if (!self.isInitIMSDK) { + V2TIMSDKConfig *config = [[V2TIMSDKConfig alloc] init]; + config.logLevel = TIM_LOG_ERROR; + self.isInitIMSDK = [self.imManager initSDK:sdkAppId config:config listener:self]; + if (!self.isInitIMSDK) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"init im sdk error."); + } + return; + } + } + if (self.isLogin) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"start login fail, you have been login, can not login twice."); + } + return; + } + @weakify(self) + [self.imManager login:userID userSig:userSig succ:^{ + @strongify(self) + if (!self) { + return; + } + self.isLogin = YES; + self.selfUserId = userID; + if (callback) { + callback(0, @"im login success."); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"im login error"); + } + }]; +} + +- (void)getSelfInfo{ + if (!self.selfUserId || [self.selfUserId isEqualToString:@""]) { + return; + } + @weakify(self) + [self.imManager getUsersInfo:@[self.selfUserId] succ:^(NSArray *infoList) { + @strongify(self) + if (!self) { return; } + if (infoList.count > 0) { + self.selfUserName = infoList.firstObject.nickName ?: @""; + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"get self info fail,code: %d reason: %@",code, desc); + }]; +} + +- (void)logout:(TXCallback)callback { + if (!self.isLogin) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"start logout fail. not login yet"); + } + return; + } + if (self.isEnterRoom) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"start logout fail. you are in room, please exit room before logout"); + } + return; + } + [self.imManager logout:^{ + if (callback) { + callback(0, @"login im success."); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc); + } + }]; +} + +- (void)setSelfProfileWithUserName:(NSString *)userName avatarUrl:(NSString *)avatarUrl callback:(TXCallback _Nullable)callback{ + if (!self.isLogin) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"set profile fail, not login yet."); + } + return; + } + V2TIMUserFullInfo *userInfo = [[V2TIMUserFullInfo alloc] init]; + userInfo.nickName = userName; + userInfo.faceURL = avatarUrl; + [self.imManager setSelfInfo:userInfo succ:^{ + if (callback) { + callback(0, @"set profile success"); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(0, desc ?: @"set profile failed."); + } + }]; +} + +- (void)createRoomWithRoomId:(NSString *)roomId + roomName:(NSString *)roomName + coverUrl:(NSString *)coverUrl + needRequest:(BOOL)needRequest + callback:(TXCallback)callback { + if (!self.isLogin) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"im not login yet, create room fail"); + } + return; + } + if (self.isEnterRoom) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"you have been in room"); + } + return; + } + self.mRoomId = roomId; + self.ownerUserId = self.selfUserId; + self.roomInfo = [[TXChatSalonRoomInfo alloc] init]; + [self.seatInfoList removeAllObjects]; // 进房时刷新 + self.roomInfo.ownerId = self.selfUserId; + self.roomInfo.ownerName = self.selfUserName; + self.roomInfo.roomName = roomName; + self.roomInfo.cover = coverUrl; + self.roomInfo.needRequest = needRequest ? 1 : 0; + @weakify(self) + [self.imManager createGroup:@"AVChatRoom" groupID:roomId groupName:roomName succ:^(NSString *groupID) { + @strongify(self) + if (!self) { + return; + } + [self setGroupInfoWithRoomId:roomId roomName:roomName coverUrl:coverUrl userName:self.selfUserName]; + [self onCreateSuccess:callback]; + } fail:^(int code, NSString *desc) { + @strongify(self) + if (!self) { + return; + } + TRTCLog(@"create room error: %d, msg: %@", code, desc); + NSString *msg = desc ?: @"create room fiald"; + if (code == 10036) { + msg = @"您当前使用的云通讯账号未开通音视频聊天室功能,创建聊天室数量超过限额,请前往腾讯云官网开通【IM音视频聊天室】,地址:https://cloud.tencent.com/document/product/269/11673"; + } else if (code == 10037) { + msg = @"单个用户可创建和加入的群组数量超过了限制,请购买相关套餐,价格地址:https://cloud.tencent.com/document/product/269/11673"; + } else if (code == 10038) { + msg = @"群成员数量超过限制,请参考,请购买相关套餐,价格地址:https://cloud.tencent.com/document/product/269/11673"; + } + + if (code == 10025 || code == 10021) { + // 表明群主是自己,认为创建成功 + // 群ID已被他人使用,走进房的逻辑 + [self setGroupInfoWithRoomId:roomId roomName:roomName coverUrl:coverUrl userName:self.selfUserName]; + [self.imManager joinGroup:roomId msg:@"" succ:^{ + TRTCLog(@"gorup has benn created. join group success"); + [self onCreateSuccess:callback]; + } fail:^(int code, NSString *desc) { + TRTCLog(@"error: group has been created. join group fail. code:%d, message: %@", code, desc); + if (callback) { + callback(code, desc ?: @""); + } + }]; + } else { + if (callback) { + callback(code, msg); + } + } + }]; +} + +- (void)destroyRoom:(TXCallback)callback { + if (!self.isOwner) { + if (callback) { + callback(-1, @"only owner could destroy room"); + } + return; + } + @weakify(self) + [self.imManager dismissGroup:self.mRoomId succ:^{ + @strongify(self) + if (!self) { + return; + } + [self unInitIMListener]; + [self cleanRoomStatus]; + if (callback) { + callback(0, @"destroy room success."); + } + } fail:^(int code, NSString *desc) { + @strongify(self) + if (!self) { + return; + } + if (code == 10007) { + TRTCLog(@"your are not real owner, start logic destroy."); + [self cleanGroupAttr]; + [self sendGroupMsg:[TXChatSalonIMJsonHandle getRoomdestroyMsg] callback:callback]; + [self unInitIMListener]; + [self cleanRoomStatus]; + } else { + if (callback) { + callback(code, desc ?: @"destroy room failed"); + } + } + }]; +} + +- (void)enterRoom:(NSString *)roomId callback:(TXCallback)callback { + [self cleanRoomStatus]; + self.mRoomId = roomId; + @weakify(self) + [self.imManager joinGroup:roomId msg:@"" succ:^{ + @strongify(self) + if (!self) { + return; + } + [self onJoinRoomSuccessWithRoomId:roomId callback:callback]; + } fail:^(int code, NSString *desc) { + @strongify(self) + if (!self) { + return; + } + if (code == 10013) { + [self onJoinRoomSuccessWithRoomId:roomId callback:callback]; + } else { + if (callback) { + callback(-1, [NSString stringWithFormat:@"join group eror, enter room fail. code:%d, msg:%@", code ,desc]); + } + } + }]; +} + +- (void)exitRoom:(TXCallback)callback { + if (!self.isEnterRoom) { + if (callback) { + callback(-1,@"not enter room yet, can't exit room."); + } + return; + } + @weakify(self) + [self.imManager quitGroup:self.mRoomId succ:^{ + @strongify(self) + if (!self) { + return; + } + [self unInitIMListener]; + [self cleanRoomStatus]; + if (callback) { + callback(0, @"exite room success."); + } + } fail:^(int code, NSString *desc) { + @strongify(self) + if (!self) { + return; + } + [self unInitIMListener]; + if (callback) { + callback(code, desc ?: @"exite room failed."); + } + }]; +} + +- (void)takeSeat:(TXCallback)callback { + if (!callback) { + callback = ^(int code, NSString* message){ + + }; + } + if ([self.seatInfoList objectForKey:self.selfUserId]) { + // 已经在麦位上了 + callback(-1, @"already on the seat"); + return; + } + TXChatSalonSeatInfo* changeInfo = [[TXChatSalonSeatInfo alloc] init]; + changeInfo.user = self.selfUserId; + changeInfo.mute = NO; + NSDictionary *dic = [TXChatSalonIMJsonHandle getSeatInfoJsonStrWithUserID:self.selfUserId info:changeInfo]; + [self modeifyGroupAttrs:dic callback:callback]; +} + +- (void)leaveSeat:(TXCallback)callback { + if (!callback) { + callback = ^(int code, NSString* message){ + + }; + } + TXChatSalonSeatInfo *info = [self.seatInfoList objectForKey:self.selfUserId]; + if (info) { + NSString *key = [NSString stringWithFormat:@"%@%@", VOICE_ROOM_KEY_SEAT, self.selfUserId]; + [self removeGroupAttrs:@[key] callback:callback]; + } else { + callback(-1, @"already leave seat."); + } +} + +- (void)pickSeat:(NSString *)userID callback:(TXCallback)callback { + if (!callback) { + callback = ^(int code, NSString* message){}; + } + if (!self.isOwner) { + callback(-1, @"only owner can pick someone on the seat."); + return; + } + if ([self.seatInfoList objectForKey:userID]) { + // 已经在麦位上了 + callback(-1, @"already on the seat"); + return; + } + TXChatSalonSeatInfo *changeInfo = [[TXChatSalonSeatInfo alloc] init]; + changeInfo.user = userID; + changeInfo.mute = NO; + NSDictionary *dic = [TXChatSalonIMJsonHandle getSeatInfoJsonStrWithUserID:userID info:changeInfo]; + [self modeifyGroupAttrs:dic callback:callback]; +} + +- (void)kickSeat:(NSString *)userID callback:(TXCallback)callback { + if (!callback) { + callback = ^(int code, NSString* message){}; + } + if (!self.isOwner) { + callback(-1, @"only owner can kick someone on the seat."); + return; + } + TXChatSalonSeatInfo *changeInfo = [self.seatInfoList objectForKey:userID]; + if (changeInfo) { + // 在麦位上 + NSString *key = [NSString stringWithFormat:@"%@%@", VOICE_ROOM_KEY_SEAT, userID]; + [self removeGroupAttrs:@[key] callback:callback]; + } else { + callback(-1, @"already leave seat."); + } +} + +- (void)muteSeat:(NSString *)userID mute:(BOOL)mute callback:(TXCallback)callback { + if (!callback) { + callback = ^(int code, NSString* message){}; + } + TXChatSalonSeatInfo *info = self.seatInfoList[userID]; + TXChatSalonSeatInfo *changeInfo = [[TXChatSalonSeatInfo alloc] init]; + changeInfo.user = info.user; + changeInfo.mute = mute; + NSDictionary *dic = [TXChatSalonIMJsonHandle getSeatInfoJsonStrWithUserID:userID info:changeInfo]; + [self modeifyGroupAttrs:dic callback:callback]; +} + +- (void)getUserInfo:(NSArray *)userList callback:(TXUserListCallback)callback { + if (!self.isEnterRoom) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"get user info list fail, not enter room yet", @[]); + } + return; + } + if (!userList || userList.count == 0) { + if (callback) { + callback(VOICE_ROOM_SERVICE_CODE_ERROR, @"get user info list fail, user id list is empty.", @[]); + } + return; + } + [self.imManager getUsersInfo:userList succ:^(NSArray *infoList) { + NSMutableArray *txUserInfo = [[NSMutableArray alloc] initWithCapacity:2]; + [infoList enumerateObjectsUsingBlock:^(V2TIMUserFullInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + TXChatSalonUserInfo *userInfo = [[TXChatSalonUserInfo alloc] init]; + userInfo.userName = obj.nickName ?: @""; + userInfo.userID = obj.userID ?: @""; + userInfo.avatarURL = obj.faceURL ?: @""; + [txUserInfo addObject:userInfo]; + }]; + if (callback) { + callback(0, @"success", txUserInfo); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"get user info failed", @[]); + } + }]; +} + +- (void)sendRoomTextMsg:(NSString *)msg callback:(TXCallback)callback { + if (!self.isEnterRoom) { + if (callback) { + callback(-1, @"send room text fail. not enter room yet."); + } + return; + } + [self.imManager sendGroupTextMessage:msg to:self.mRoomId priority:V2TIM_PRIORITY_NORMAL succ:^{ + if (callback) { + callback(0, @"send gourp message success."); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"send group message error."); + } + }]; +} + +- (void)sendRoomCustomMsg:(NSString *)cmd message:(NSString *)message callback:(TXCallback)callback { + if (!self.isEnterRoom) { + if (callback) { + callback(-1, @"send room text fail. not enter room yet."); + } + return; + } + [self sendGroupMsg:[TXChatSalonIMJsonHandle getCusMsgJsonStrWithCmd:cmd msg:message] callback:callback]; +} + +- (void)sendGroupMsg:(NSString *)message callback:(TXCallback)callback { + if (!self.mRoomId || [self.mRoomId isEqualToString:@""]) { + if (callback) { + callback(-1, @"gourp id is wrong.please check it."); + } + return; + } + NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding]; + if (!data) { + callback(-1, @"message can't covert to data"); + return; + } + [self.imManager sendGroupCustomMessage:data to:self.mRoomId priority:V2TIM_PRIORITY_NORMAL succ:^{ + if (callback) { + callback(0, @"send group message success."); + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"error: send group message error. error:%d, message:%@", code, desc); + if (callback) { + callback(code, desc); + } + }]; +} + +- (void)getAudienceList:(TXUserListCallback)callback { + [self.imManager getGroupMemberList:self.mRoomId filter:V2TIM_GROUP_MEMBER_FILTER_COMMON nextSeq:0 succ:^(uint64_t nextSeq, NSArray *memberList) { + if (memberList) { + NSMutableArray *resultList = [[NSMutableArray alloc] initWithCapacity:2]; + [memberList enumerateObjectsUsingBlock:^(V2TIMGroupMemberFullInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + TXChatSalonUserInfo *info = [[TXChatSalonUserInfo alloc] init]; + info.userID = obj.userID; + info.userName = obj.nickName; + info.avatarURL = obj.faceURL; + [resultList addObject:info]; + }]; + if (callback) { + callback(0, @"get audience list success.", resultList); + } + } else { + if (callback) { + callback(-1, @"get audience list fail, results is nil", @[]); + } + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"get sudience list fail.", @[]); + } + }]; +} + +- (void)getRoomInfoList:(NSArray *)roomIds calback:(TXChatSalonRoomInfoListCallback)callback { + [self.imManager getGroupsInfo:roomIds succ:^(NSArray *groupResultList) { + if (groupResultList) { + NSMutableArray *groupResults = [[NSMutableArray alloc] initWithCapacity:2]; + NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithCapacity:2]; + [groupResultList enumerateObjectsUsingBlock:^(V2TIMGroupInfoResult * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + if (obj && obj.info.groupID) { + tempDic[obj.info.groupID] = obj; + } + }]; + [roomIds enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + TXChatSalonRoomInfo *roomInfo = [[TXChatSalonRoomInfo alloc] init]; + V2TIMGroupInfoResult* groupInfo = tempDic[obj]; + if (groupInfo) { + roomInfo.roomId = groupInfo.info.groupID; + roomInfo.cover = groupInfo.info.faceURL; + roomInfo.memberCount = groupInfo.info.memberCount; + roomInfo.ownerId = groupInfo.info.owner; + roomInfo.roomName = groupInfo.info.groupName; + roomInfo.ownerName = groupInfo.info.introduction; + } + [groupResults addObject:roomInfo]; + }]; + if (callback) { + callback(0, @"success.", groupResults); + } + } else { + if (callback) { + callback(-1, @"get group info failed. result is nil.", @[]); + } + } + } fail:^(int code, NSString *desc) { + + }]; +} + +- (void)destroy { + +} + +- (NSString *)sendInvitation:(NSString *)cmd userID:(NSString *)userID content:(NSString *)content callback:(TXCallback)callback { + NSString* jsonString = [TXChatSalonIMJsonHandle getInvitationMsgWithRoomId:self.mRoomId cmd:cmd content:content]; + return [self.imManager invite:userID data:jsonString timeout:0 succ:^{ + TRTCLog(@"send invitation success."); + if (callback) { + callback(0, @"send invitation success."); + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"send invitation failed"); + if (callback) { + callback(code, desc ?: @"send invatiaon failed"); + } + }]; +} + +- (void)acceptInvitation:(NSString *)identifier callback:(TXCallback)callback { + TRTCLog(@"accept %@", identifier); + [self.imManager accept:identifier data:nil succ:^{ + TRTCLog(@"accept invitation success."); + if (callback) { + callback(0, @"accept invitation success."); + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"accept invitation failed"); + if (callback) { + callback(code, desc ?: @"accept invatiaon failed"); + } + }]; +} + +- (void)rejectInvitaiton:(NSString *)identifier callback:(TXCallback)callback { + TRTCLog(@"reject %@", identifier); + [self.imManager reject:identifier data:nil succ:^{ + TRTCLog(@"reject invitation success."); + if (callback) { + callback(0, @"reject invitation success."); + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"reject invitation failed"); + if (callback) { + callback(code, desc ?: @"reject invatiaon failed"); + } + }]; +} + +- (void)cancelInvitation:(NSString *)identifier callback:(TXCallback)callback { + TRTCLog(@"cancel %@", identifier); + [self.imManager cancel:identifier data:nil succ:^{ + TRTCLog(@"cancel invitation success."); + if (callback) { + callback(0, @"cancel invitation success."); + } + } fail:^(int code, NSString *desc) { + TRTCLog(@"cancel invitation success."); + if (callback) { + callback(0, @"cancel invitation success."); + } + }]; +} +#pragma mark - V2TIMSDKListener + +#pragma mark - V2TIMSimpleMsgListener +- (void)onRecvC2CTextMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info text:(NSString *)text { + +} + +- (void)onRecvC2CCustomMessage:(NSString *)msgID sender:(V2TIMUserInfo *)info customData:(NSData *)data { + +} + +- (void)onRecvGroupTextMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info text:(NSString *)text { + TRTCLog(@"im get tet msg group:%@, userID:%@, text:%@", groupID, info.userID, text); + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + TXChatSalonUserInfo* userInfo = [[TXChatSalonUserInfo alloc] init]; + userInfo.userID = info.userID; + userInfo.avatarURL = info.faceURL; + userInfo.userName = info.nickName; + if ([self canDelegateResponseMethod:@selector(onRoomRecvRoomTextMsg:message:userInfo:)]) { + [self.delegate onRoomRecvRoomTextMsg:self.mRoomId message:text userInfo:userInfo]; + } +} + +- (void)onRecvGroupCustomMessage:(NSString *)msgID groupID:(NSString *)groupID sender:(V2TIMGroupMemberInfo *)info customData:(NSData *)data { + TRTCLog(@"im get custom msg group:%@, userID:%@, text:%@", groupID, info.userID, data); + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + if (!data) { + return; + } + NSString* jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + NSDictionary* dic = [jsonString mj_JSONObject]; + NSString *version = [dic objectForKey:VOICE_ROOM_KEY_ATTR_VERSION]; + if (!version || ![version isEqualToString:VOICE_ROOM_VALUE_ATTR_VERSION]) { + TRTCLog(@"protocol version is not match, ignore msg"); + return; + } + NSNumber* action = [dic objectForKey:VOICE_ROOM_KEY_CMD_ACTION]; + if (!action) { + TRTCLog(@"action can't parse from data"); + return; + } + int actionValue = [action intValue]; + switch (actionValue) { + case kChatSalonCodeUnknown: + break; + case kChatSalonCodeCustomMsg: + { + NSDictionary *cusPair = [TXChatSalonIMJsonHandle parseCusMsgWithJsonDic:dic]; + TXChatSalonUserInfo *userInfo = [[TXChatSalonUserInfo alloc] init]; + userInfo.userID = info.userID; + userInfo.avatarURL = info.faceURL; + userInfo.userName = info.nickName; + if ([self canDelegateResponseMethod:@selector(onRoomRecvRoomCustomMsg:cmd:message:userInfo:)]) { + [self.delegate onRoomRecvRoomCustomMsg:self.mRoomId cmd:cusPair[@"cmd"] message:cusPair[@"message"] userInfo:userInfo]; + } + } + break; + case kChatSalonCodeDestroy: + { + [self exitRoom:nil]; + if ([self canDelegateResponseMethod:@selector(onRoomDestroyWithRoomId:)]) { + [self.delegate onRoomDestroyWithRoomId:self.mRoomId]; + } + [self cleanRoomStatus]; + } + break; + default: + break; + } +} +#pragma mark - V2TIMGroupListener +- (void)onMemberEnter:(NSString *)groupID memberList:(NSArray *)memberList{ + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + [memberList enumerateObjectsUsingBlock:^(V2TIMGroupMemberInfo * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { + TXChatSalonUserInfo* userInfo = [[TXChatSalonUserInfo alloc] init]; + userInfo.userID = obj.userID; + userInfo.avatarURL = obj.faceURL; + userInfo.userName = obj.nickName; + if ([self canDelegateResponseMethod:@selector(onRoomAudienceEnter:)]) { + [self.delegate onRoomAudienceEnter:userInfo]; + } + }]; +} + +- (void)onMemberLeave:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member{ + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + if (!member) { + return; + } + TXChatSalonUserInfo *userInfo = [[TXChatSalonUserInfo alloc] init]; + userInfo.userID = member.userID; + userInfo.avatarURL = member.faceURL; + userInfo.userName = member.nickName; + if ([self canDelegateResponseMethod:@selector(onRoomAudienceLeave:)]) { + [self.delegate onRoomAudienceLeave:userInfo]; + } +} + +- (void)onGroupDismissed:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser{ + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + [self cleanRoomStatus]; + if ([self canDelegateResponseMethod:@selector(onRoomDestroyWithRoomId:)]) { + [self.delegate onRoomDestroyWithRoomId:groupID]; + } +} + +- (void)onGroupAttributeChanged:(NSString *)groupID attributes:(NSMutableDictionary *)attributes{ + TRTCLog(@"on group attr changed:%@", attributes); + if (![groupID isEqualToString:self.mRoomId]) { + return; + } + if (!attributes) { + TRTCLog(@"attributes error"); + return; + } + NSDictionary *seatInfoList = [TXChatSalonIMJsonHandle getSeatListFromAttr:attributes]; + NSDictionary *oldSeatInfoList = [self.seatInfoList copy]; + self.seatInfoList = [seatInfoList mutableCopy]; + NSSet* allKeys = [NSSet setWithArray:oldSeatInfoList.allKeys]; + allKeys = [allKeys setByAddingObjectsFromArray:seatInfoList.allKeys]; + for (NSString *key in allKeys) { + TXChatSalonSeatInfo *old = [oldSeatInfoList objectForKey:key]; + TXChatSalonSeatInfo *new = [seatInfoList objectForKey:key]; + if (old == nil & new != nil) { + // 有人进入 + [self onSeatTakeWithUser:new.user]; + } + if (old != nil & new == nil) { + [self onSeatLeaveWithUser:old.user]; + } + if ((old != nil & new != nil) & (old.mute != new.mute)) { + [self onSeatMuteWithUser:new.user mute:new.mute]; + } + if (old == nil && new == nil) { + NSAssert(NO, @"seat info error, old and new info all be nil."); + } + } +} + + +#pragma mark - V2TIMSignalingListener +- (void)onReceiveNewInvitation:(NSString *)inviteID inviter:(NSString *)inviter groupID:(NSString *)groupID inviteeList:(NSArray *)inviteeList data:(NSString *)data{ + TXChatSalonInviteData *result = [TXChatSalonIMJsonHandle parseInvitationMsgWithJson:data]; + if (!result) { + TRTCLog(@"parse data error"); + return; + } + if (![result.roomId isEqualToString:self.mRoomId]) { + TRTCLog(@"room id is not right"); + return; + } + if ([self canDelegateResponseMethod:@selector(onReceiveNewInvitationWithIdentifier:inviter:cmd:content:)]) { + [self.delegate onReceiveNewInvitationWithIdentifier:inviteID inviter:inviter cmd:result.command content:result.message]; + } +} + +- (void)onInviteeAccepted:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data { + if ([self canDelegateResponseMethod:@selector(onInviteeAcceptedWithIdentifier:invitee:)]) { + [self.delegate onInviteeAcceptedWithIdentifier:inviteID invitee:invitee]; + } +} + +-(void)onInviteeRejected:(NSString *)inviteID invitee:(NSString *)invitee data:(NSString *)data { + if ([self canDelegateResponseMethod:@selector(onInviteeRejectedWithIdentifier:invitee:)]) { + [self.delegate onInviteeRejectedWithIdentifier:inviteID invitee:invitee]; + } +} + +- (void)onInvitationCancelled:(NSString *)inviteID inviter:(NSString *)inviter data:(NSString *)data { + if ([self canDelegateResponseMethod:@selector(onInviteeCancelledWithIdentifier:invitee:)]) { + [self.delegate onInviteeCancelledWithIdentifier:inviteID invitee:inviter]; + } +} + +#pragma mark - private method +- (V2TIMManager *)imManager { + return [V2TIMManager sharedInstance]; +} + +- (BOOL)isOwner { + return [self.selfUserId isEqualToString:self.ownerUserId]; +} + +- (void)cleanRoomStatus { + self.isEnterRoom = NO; + self.mRoomId = @""; + self.ownerUserId = @""; +} + +- (BOOL)canDelegateResponseMethod:(SEL)method { + return self.delegate && [self.delegate respondsToSelector:method]; +} + +- (void)onSeatTakeWithUser:(NSString *)userID { + TRTCLog(@"onSeatTake: %ld, user: %@", (long)index, userID); + @weakify(self) + [self getUserInfo:@[userID] callback:^(int code, NSString * _Nonnull message, NSArray * _Nonnull userInfos) { + @strongify(self) + if (!self) { + return; + } + TXChatSalonUserInfo *userInfo = [[TXChatSalonUserInfo alloc] init]; + if (code == 0 && userInfos.count > 0) { + userInfo = userInfos[0]; + } else { + TRTCLog(@"onSeat Take get user info error!"); + userInfo.userID = userID; + userInfo.userName = userID; + // TODO: 添加默认用户头像 + } + if ([self canDelegateResponseMethod:@selector(onSeatTakeWithUserInfo:)]) { + [self.delegate onSeatTakeWithUserInfo:userInfo]; + } + }]; +} + +- (void)onSeatLeaveWithUser:(NSString *)userID { + TRTCLog(@"onSeatLeave user: %@", userID); + @weakify(self) + [self getUserInfo:@[userID] callback:^(int code, NSString * _Nonnull message, NSArray * _Nonnull userInfos) { + @strongify(self) + if (!self) { + return; + } + TXChatSalonUserInfo *userInfo = [[TXChatSalonUserInfo alloc] init]; + if (code == 0 && userInfos.count > 0) { + userInfo = userInfos[0]; + } else { + TRTCLog(@"onSeat Take get user info error!"); + userInfo.userID = userID; + userInfo.userName = userID; + } + if ([self canDelegateResponseMethod:@selector(onSeatLeaveWithUserInfo:)]) { + [self.delegate onSeatLeaveWithUserInfo:userInfo]; + } + }]; +} + +- (void)onSeatMuteWithUser:(NSString *)userID mute:(BOOL)mute { + TRTCLog(@"onSeatMute: %@, mute:%d", userID, mute); + if ([self canDelegateResponseMethod:@selector(onSeatMuteWithUser:mute:)]) { + [self.delegate onSeatMuteWithUser:userID mute:mute]; + } +} + +- (void)initImListener { + [self.imManager setGroupListener:self]; + // 设置前先remove下,防止在单例的情况下重复设置 + [self.imManager removeSignalingListener:self]; + [self.imManager removeSimpleMsgListener:self]; + [self.imManager addSignalingListener:self]; + [self.imManager addSimpleMsgListener:self]; +} + +- (void)unInitIMListener { + [self.imManager setGroupListener:nil]; + [self.imManager removeSignalingListener:self]; + [self.imManager removeSimpleMsgListener:self]; +} + +- (void)onCreateSuccess:(TXCallback _Nullable)callback { + [self initImListener]; + @weakify(self) + [self.imManager initGroupAttributes:self.mRoomId + attributes:[TXChatSalonIMJsonHandle getInitRoomDicWithRoomInfo:self.roomInfo seatInfoList:self.seatInfoList] + succ:^{ + @strongify(self) + if (!self) { return; } + self.isEnterRoom = YES; + if (callback) { + callback(0, @"init room info and seat success"); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"init group attributes failed"); + } + }]; +} + +- (void)onJoinRoomSuccessWithRoomId:(NSString *)roomId callback:(TXCallback _Nullable)callback { + @weakify(self) + [self.imManager getGroupAttributes:roomId keys:nil succ:^(NSMutableDictionary *groupAttributeList) { + @strongify(self) + if (!self) { + return; + } + [self initImListener]; + if (!groupAttributeList) { + return; + } + // 解析roomInfo + TXChatSalonRoomInfo* roomInfo = [TXChatSalonIMJsonHandle getRoomInfoFromAttr:groupAttributeList]; + if (roomInfo) { + roomInfo.roomId = roomId; + roomInfo.memberCount = -1; // 当前房间的MemberCount无法从这个接口正确获取。 + self.roomInfo = roomInfo; + } else { + TRTCLog(@"group room info is empty, enter room failed."); + if (callback) { + callback(-1, @"group room info is empty, enter room failed."); + } + return; + } + TRTCLog(@"enter room successed."); + self.mRoomId = roomId; + self.seatInfoList = [[TXChatSalonIMJsonHandle getSeatListFromAttr:groupAttributeList] mutableCopy]; + self.isEnterRoom = true; + self.ownerUserId = self.roomInfo.ownerId; + if ([self canDelegateResponseMethod:@selector(onRoomInfoChange:)]) { + [self.delegate onRoomInfoChange:self.roomInfo]; + } + if ([self canDelegateResponseMethod:@selector(onSeatInfoListChange:)]) { + [self.delegate onSeatInfoListChange:self.seatInfoList]; + } + if (callback) { + callback(0, @"enter rooom success"); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"get group attr error"); + } + }]; +} + +- (void)cleanGroupAttr { + [self.imManager deleteGroupAttributes:self.mRoomId keys:nil succ:nil fail:nil]; +} + +- (void)modeifyGroupAttrs:(NSDictionary *)attrs callback:(TXCallback _Nullable)callback { + [self.imManager setGroupAttributes:self.mRoomId attributes:attrs succ:^{ + if (callback) { + callback(0, @"modify group attrs success"); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"modify group attrs failed"); + } + }]; +} + +- (void)removeGroupAttrs:(NSArray *)attrKeys callback:(TXCallback _Nullable)callback { + [self.imManager deleteGroupAttributes:self.mRoomId keys:attrKeys succ:^{ + if (callback) { + callback(0, @"delete group attrs success"); + } + } fail:^(int code, NSString *desc) { + if (callback) { + callback(code, desc ?: @"delete group attrs failed"); + } + }]; +} + +- (void)setGroupInfoWithRoomId:(NSString *)roomId roomName:(NSString *)roomName coverUrl:(NSString *)coverUrl userName:(NSString *)userName { + V2TIMGroupInfo *info = [[V2TIMGroupInfo alloc] init]; + info.groupID = roomId; + info.groupName = roomName; + info.faceURL = coverUrl; + info.introduction = userName; + [self.imManager setGroupInfo:info succ:^{ + TRTCLog(@"success: set group info success."); + } fail:^(int code, NSString *desc) { + TRTCLog(@"fail: set group info fail."); + }]; +} + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.h new file mode 100644 index 00000000..96e294aa --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.h @@ -0,0 +1,72 @@ +// +// ChatSalonTRTCService.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/1. +// Copyright © 2020 tencent. All rights reserved. +// + +#import +#import "TXChatSalonBaseDef.h" + +NS_ASSUME_NONNULL_BEGIN + +#define kTRTCRoleAnchorValue 20 +#define kTRTCRoleAudienceValue 21 + +@class TRTCQualityInfo; +@class TRTCVolumeInfo; +@class TRTCAudioRecordingParams; + +@protocol ChatSalonTRTCServiceDelegate + +- (void)onTRTCAnchorEnter:(NSString *)userID; +- (void)onTRTCAnchorExit:(NSString *)userID; +- (void)onTRTCAudioAvailable:(NSString *)userID available:(BOOL)available; +- (void)onError:(NSInteger)code message:(NSString *)message; +- (void)onNetWorkQuality:(TRTCQualityInfo *)trtcQuality arrayList:(NSArray *)arrayList; +- (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume; + +@end + +@interface ChatSalonTRTCService : NSObject + +@property (nonatomic, weak) id delegate; + ++ (instancetype)sharedInstance; + +- (void)enterRoomWithSdkAppId:(UInt32)sdkAppId roomId:(NSString *)roomId userID:(NSString *)userID userSign:(NSString *)userSign role:(NSInteger)role callback:(TXCallback _Nullable)callback; + +- (void)exitRoom:(TXCallback _Nullable)callback; + +- (void)muteLocalAudio:(BOOL)isMute; + +- (void)muteRemoteAudioWithUserId:(NSString *)userID isMute:(BOOL)isMute; + +- (void)muteAllRemoteAudio:(BOOL)isMute; + +- (void)setAudioQuality:(NSInteger)quality; + +- (void)startMicrophone; + +- (void)stopMicrophone; + +- (void)switchToAnchor; + +- (void)switchToAudience; + +- (void)setSpeaker:(BOOL)userSpeaker; + +- (void)setAudioCaptureVolume:(NSInteger)volume; + +- (void)setAudioPlayoutVolume:(NSInteger)volume; + +- (void)startFileDumping:(TRTCAudioRecordingParams *)params; + +- (void)stopFileDumping; + +- (void)enableAudioEvalutation:(BOOL)enable; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.m b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.m new file mode 100644 index 00000000..14b09c29 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/Impl/trtc/ChatSalonTRTCService.m @@ -0,0 +1,236 @@ +// +// ChatSalonTRTCService.m +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/7/1. +// Copyright © 2020 tencent. All rights reserved. +// + +#import "ChatSalonTRTCService.h" +#import "TRTCCloud.h" + +@interface ChatSalonTRTCService () + +@property (nonatomic, assign) BOOL isInRoom; +@property (nonatomic, strong) NSString *userID; +@property (nonatomic, strong) NSString *roomId; +@property (nonatomic, strong) TRTCParams *mTRTCParms; +@property (nonatomic, copy) TXCallback enterRoomCallback; +@property (nonatomic, copy) TXCallback exitRoomCallback; + +@property (nonatomic, strong, readonly)TRTCCloud *mTRTCCloud; + +@end + +@implementation ChatSalonTRTCService + +- (TRTCCloud *)mTRTCCloud { + return [TRTCCloud sharedInstance]; +} + ++ (instancetype)sharedInstance{ + static ChatSalonTRTCService* instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[ChatSalonTRTCService alloc] init]; + }); + return instance; +} + +- (void)enterRoomWithSdkAppId:(UInt32)sdkAppId + roomId:(NSString *)roomId + userID:(NSString *)userID + userSign:(NSString *)userSign + role:(NSInteger)role + callback:(TXCallback)callback { + BOOL isParamError = NO; + if (roomId == nil || [roomId isEqualToString:@""]) { + isParamError = YES; + } + if (userID == nil || [userID isEqualToString:@""]) { + isParamError = YES; + } + if (userSign == nil || [userSign isEqualToString:@""]) { + isParamError = YES; + } + int roomIdIntValue = [roomId intValue]; + if (roomIdIntValue == 0) { + isParamError = YES; + } + if (isParamError) { + TRTCLog(@"error: enter trtc room fail. params invalid. room id:%@, userID:%@, userSig is empty:%d", roomId, userID, (userSign == nil || [userSign isEqualToString:@""])); + callback(-1, @"enter trtc room fail."); + return; + } + self.userID = userID; + self.roomId = roomId; + self.enterRoomCallback = callback; + TRTCLog(@"enter room. app id:%u, room id: %@, userID: %@", (unsigned int)sdkAppId, roomId, userID); + TRTCParams * parms = [[TRTCParams alloc] init]; + parms.sdkAppId = sdkAppId; + parms.userId = userID; + parms.userSig = userSign; + parms.role = role == 20 ? TRTCRoleAnchor : TRTCRoleAudience; + parms.roomId = roomIdIntValue; + self.mTRTCParms = parms; + [self internalEnterRoom]; +} + +- (void)exitRoom:(TXCallback)callback { + TRTCLog(@"exit trtc room."); + self.userID = nil; + self.mTRTCParms = nil; + self.enterRoomCallback = nil; + self.exitRoomCallback = callback; + [self.mTRTCCloud exitRoom]; +} + +- (void)muteLocalAudio:(BOOL)isMute { + [self.mTRTCCloud muteLocalAudio:isMute]; +} + +- (void)muteRemoteAudioWithUserId:(NSString *)userID isMute:(BOOL)isMute { + [self.mTRTCCloud muteRemoteAudio:userID mute:isMute]; +} + +- (void)muteAllRemoteAudio:(BOOL)isMute { + [self.mTRTCCloud muteAllRemoteAudio:isMute]; +} + +- (void)setAudioQuality:(NSInteger)quality { + TRTCAudioQuality targetQuality = TRTCAudioQualityDefault; + switch (quality) { + case 1: + targetQuality = TRTCAudioQualitySpeech; + break; + case 3: + targetQuality = TRTCAudioQualityMusic; + default: + break; + } + [self.mTRTCCloud setAudioQuality:targetQuality]; +} + +- (void)startMicrophone { + [self.mTRTCCloud startLocalAudio]; +} + +- (void)stopMicrophone { + [self.mTRTCCloud stopLocalAudio]; +} + +- (void)switchToAnchor { + [self.mTRTCCloud switchRole:TRTCRoleAnchor]; + [self.mTRTCCloud startLocalAudio:TRTCAudioQualityDefault]; +} + +- (void)switchToAudience { + [self.mTRTCCloud stopLocalAudio]; + [self.mTRTCCloud switchRole:TRTCRoleAudience]; +} + +- (void)setSpeaker:(BOOL)userSpeaker { + [self.mTRTCCloud setAudioRoute:userSpeaker ? TRTCAudioModeSpeakerphone : TRTCAudioModeEarpiece]; +} + +- (void)setAudioCaptureVolume:(NSInteger)volume { + [self.mTRTCCloud setAudioCaptureVolume:volume]; +} + +- (void)setAudioPlayoutVolume:(NSInteger)volume { + [self.mTRTCCloud setAudioPlayoutVolume:volume]; +} + +- (void)startFileDumping:(TRTCAudioRecordingParams *)params { + [self.mTRTCCloud startAudioRecording:params]; +} + +- (void)stopFileDumping { + [self.mTRTCCloud stopAudioRecording]; +} + +- (void)enableAudioEvalutation:(BOOL)enable { + [self.mTRTCCloud enableAudioVolumeEvaluation:enable ? 300 : 0]; +} + +#pragma mark - private method +- (void)internalEnterRoom{ + if (self.mTRTCParms) { + self.mTRTCCloud.delegate = self; + [self enableAudioEvalutation:YES]; + [self.mTRTCCloud enterRoom:self.mTRTCParms appScene:TRTCAppSceneVoiceChatRoom]; + } +} + +- (BOOL)canDelegateResponseMethod:(SEL)method { + return self.delegate && [self.delegate respondsToSelector:method]; +} + +#pragma mark - TRTCCloudDelegate +- (void)onEnterRoom:(NSInteger)result{ + TRTCLog(@"on enter trtc room. result:%ld", (long)result); + if (result > 0) { + self.isInRoom = YES; + if (self.enterRoomCallback) { + self.enterRoomCallback(0, @"enter trtc room success."); + } + } else { + self.isInRoom = NO; + if (self.enterRoomCallback) { + self.enterRoomCallback((int)result, @"enter trtc room fail."); + } + } + self.enterRoomCallback = nil; +} + +- (void)onExitRoom:(NSInteger)reason { + TRTCLog(@"on exit trtc room. reslut: %ld", (long)reason); + self.isInRoom = NO; + if (self.exitRoomCallback) { + self.exitRoomCallback(0, @"exite room success"); + } + self.exitRoomCallback = nil; +} + +- (void)onRemoteUserEnterRoom:(NSString *)userID { + TRTCLog(@"on user enter, userid: %@", userID); + if ([self canDelegateResponseMethod:@selector(onTRTCAnchorEnter:)]) { + [self.delegate onTRTCAnchorEnter:userID]; + } +} + +- (void)onRemoteUserLeaveRoom:(NSString *)userID reason:(NSInteger)reason { + if ([self canDelegateResponseMethod:@selector(onTRTCAnchorExit:)]) { + [self.delegate onTRTCAnchorExit:userID]; + } +} + +- (void)onUserAudioAvailable:(NSString *)userID available:(BOOL)available { + if ([self canDelegateResponseMethod:@selector(onTRTCAudioAvailable:available:)]) { + [self.delegate onTRTCAudioAvailable:userID available:available]; + } +} + +- (void)onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo{ + if ([self canDelegateResponseMethod:@selector(onError:message:)]) { + [self.delegate onError:errCode message:errMsg]; + } +} + +- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality remoteQuality:(NSArray *)remoteQuality { + if ([self canDelegateResponseMethod:@selector(onNetworkQuality:remoteQuality:)]) { + [self.delegate onNetWorkQuality:localQuality arrayList:remoteQuality]; + } +} + +- (void)onUserVoiceVolume:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume { + if ([self canDelegateResponseMethod:@selector(onUserVoiceVolume:totalVolume:)]) { + [self.delegate onUserVoiceVolume:userVolumes totalVolume:totalVolume]; + } +} + +- (void)onSetMixTranscodingConfig:(int)err errMsg:(NSString *)errMsg{ + TRTCLog(@"on set mix transcoding, code:%d, msg: %@", err, errMsg); +} + +@end diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalon.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalon.h new file mode 100644 index 00000000..c00ef0f3 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalon.h @@ -0,0 +1,305 @@ +// +// TRTCChatSalon.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import +#import "TRTCChatSalonDelegate.h" +#import "TRTCChatSalonDef.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TXAudioEffectManager; +@interface TRTCChatSalon : NSObject + +/** +* 获取 TRTCChatSalon 单例对象 +* +* - returns: TRTCChatSalon 实例 +* - note: 可以调用 {@link TRTCChatSalon#destroySharedInstance()} 销毁单例对象 +*/ ++ (instancetype)sharedInstance NS_SWIFT_NAME(shared()); + +/** +* 销毁 TRTCChatSalon 单例对象 +* +* - note: 销毁实例后,外部缓存的 TRTCChatSalon 实例不能再使用,需要重新调用 {@link TRTCChatSalon#sharedInstance()} 获取新实例 +*/ ++ (void)destroySharedInstance NS_SWIFT_NAME(destroyShared()); + +#pragma mark: - 基础接口 +/** +* 设置组件回调接口 +*

+* 您可以通过 TRTCChatSalonDelegate 获得 TRTCChatSalon 的各种状态通知 +* +* - parameter delegate 回调接口 +* - note: TRTCChatSalon 中的回调事件,默认是在 Main Queue 中回调给您;如果您需要指定事件回调所在的队列,可使用 {@link TRTCChatSalon#setDelegateQueue(queue)} +*/ +- (void)setDelegate:(id)delegate NS_SWIFT_NAME(setDelegate(delegate:)); + +/** +* 设置事件回调所在的队列 +* +* - parameter queue 队列,TRTCChatSalon 中的各种状态通知回调,会派发到您指定的queue。 +*/ +- (void)setDelegateQueue:(dispatch_queue_t)queue NS_SWIFT_NAME(setDelegateQueue(queue:)); + +/** +* 登录 +* +* - parameter sdkAppID 您可以在实时音视频控制台 >【[应用管理](https://console.cloud.tencent.com/trtc/app)】> 应用信息中查看 SDKAppID +* - parameter userID 当前用户的 ID,字符串类型,只允许包含英文字母(a-z 和 A-Z)、数字(0-9)、连词符(-)和下划线(\_) +* - parameter userSig 腾讯云设计的一种安全保护签名,获取方式请参考 [如何计算 UserSig](https://cloud.tencent.com/document/product/647/17275)。 +* - parameter callback 登录回调,成功时 code 为 0 +*/ +- (void)login:(int)sdkAppID + userID:(NSString *)userID + userSig:(NSString *)userSig + callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(login(sdkAppID:userID:userSig:callback:)); + +/** +* 退出登录 +*/ +- (void)logout:(ActionCallback _Nullable)callback NS_SWIFT_NAME(logout(callback:)); + + +/** +* 设置用户信息,您设置的用户信息会被存储于腾讯云 IM 云服务中。 +* +* - parameter userName 用户昵称, 不能为nil +* - parameter avatarURL 用户头像 +* - parameter callback 是否设置成功的结果回调 +*/ +- (void)setSelfProfile:(NSString *)userName avatarURL:(NSString *)avatarURL callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(setSelfProfile(userName:avatarURL:callback:)); + +#pragma mark - 房间管理接口 +/** +* 创建房间(主播调用) +* +* 主播正常的调用流程是: +* 1. 主播调用`createRoom`创建新的语音聊天室,此时传入房间 ID、上麦是否需要房主确认、麦位数等房间属性信息。 +* 2. 主播创建房间成功后,调用`enterSeat`进入座位。 +* 3. 主播还会收到麦位表有成员进入的`onAnchorEnterSeat`的事件通知,此时会自动打开麦克风采集。 +* +* - parameter roomID 房间标识,需要由您分配并进行统一管理。 +* - parameter roomParam 房间信息,用于房间描述的信息,例如房间名称,封面信息等。如果房间列表和房间信息都由您的服务器自行管理,可忽略该参数。 +* - parameter callback 创建房间的结果回调,成功时 code 为0. +*/ +- (void)createRoom:(int)roomID roomParam:(ChatSalonParam *)roomParam callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(createRoom(roomID:roomParam:callback:)); + +/** +* 销毁房间(主播调用) +* +* 主播在创建房间后,可以调用这个函数来销毁房间。 +*/ +- (void)destroyRoom:(ActionCallback _Nullable)callback NS_SWIFT_NAME(destroyRoom(callback:)); + +/** +* 进入房间(观众调用) +* +* 观众观看直播的正常调用流程如下: +* 1.【观众】向您的服务端获取最新的语音聊天室列表,可能包含多个直播间的 roomId 和房间信息。 +* 2. 观众选择一个语音聊天室,调用`enterRoom`并传入房间号即可进入该房间。 +* 3. 进房后会收到组件的`onRoomInfoChange`房间属性变化事件通知,此时可以记录房间属性并做相应改变,例如 UI 展示房间名、记录上麦是否需要请求主播同意等。 +* 4. 进房后会收到组件的`onEnterRoomSeatListNotify`麦位表变化事件通知,此时可以将麦位表变化刷新到 UI 界面上。 +* 5. 进房后还会收到麦位表有主播进入的`onAnchorEnterSeat`的事件通知。 +* +* - parameter roomID 房间标识 +* - parameter callback 进入房间是否成功的结果回调 +*/ +- (void)enterRoom:(NSInteger)roomID callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(enterRoom(roomID:callback:)); + +/** +* 退出房间 +* +* - parameter callback 退出房间是否成功的结果回调 +*/ +- (void)exitRoom:(ActionCallback _Nullable)callback NS_SWIFT_NAME(exitRoom(callback:)); + +/** +* 获取房间列表的详细信息 +* +* 其中的信息是主播在创建 `createRoom()` 时通过 roomParam 设置进来的,如果房间列表和房间信息都由您的服务器自行管理,此函数您可以不用关心。 +* +* - parameter roomIdList 房间号列表 +* - parameter callback 房间详细信息回调 +*/ +- (void)getRoomInfoList:(NSArray *)roomIdList callback:(ChatSalonInfoCallback _Nullable)callback NS_SWIFT_NAME(getRoomInfoList(roomIdList:callback:)); + +/** +* 获取指定userID的用户信息,如果为null,则获取房间内所有人的信息 +* +* - parameter userIDList 用户id列表 +* - parameter callback 用户详细信息回调 +*/ +- (void)getUserInfoList:(NSArray * _Nullable)userIDList callback:(ChatSalonUserListCallback _Nullable)callback NS_SWIFT_NAME(getUserInfoList(userIDList:callback:)); + +#pragma mark - 麦位管理接口 +/** +* 主动上麦(观众端和主播均可调用) +* +* - parameter callback 操作回调 +*/ +- (void)enterSeat:(ActionCallback _Nullable)callback +NS_SWIFT_NAME(enterSeat(callback:)); + +/** +* 主动下麦(观众端和主播均可调用) +* +* - parameter callback 操作回调 +*/ +- (void)leaveSeat:(ActionCallback _Nullable)callback +NS_SWIFT_NAME(leaveSeat(callback:)); + +/** +* 抱人上麦(主播调用) +* +* 主播抱人上麦,房间内所有成员会收到`onAnchorEnterSeat`的事件通知。 +* +* - parameter userID 用户id +* - parameter callback 操作回调 +*/ +- (void)pickSeat:(NSString *)userID callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(pickSeat(userID:callback:)); + +/** + * 踢人下麦(主播调用) + * + * 主播踢人下麦,房间内所有成员会收到`onAnchorLeaveSeat`的事件通知。 + * + * - parameter userID 需要踢下麦的用户id + * - parameter callback 操作回调 + */ +- (void)kickSeat:(NSString *)userID callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(kickSeat(userID:callback:)); + +#pragma mark - 本地音频操作接口 + +/** +* 开启麦克风采集 +*/ +- (void)startMicrophone; + +/** +* 停止麦克风采集 +*/ +- (void)stopMicrophone; + +/** +* 设置音质 +* +* - parameter quality TRTC_AUDIO_QUALITY_MUSIC/TRTC_AUDIO_QUALITY_DEFAULT/TRTC_AUDIO_QUALITY_SPEECH +*/ +- (void)setAuidoQuality:(NSInteger)quality NS_SWIFT_NAME(setAuidoQuality(quality:)); + +/** +* 开启本地静音 +* +* - parameter mute 是否静音 +*/ +- (void)muteLocalAudio:(BOOL)mute NS_SWIFT_NAME(muteLocalAudio(mute:)); + +/** +* 设置开启扬声器 +* +* - parameter useSpeaker true : 扬声器,false : 听筒 +*/ +- (void)setSpeaker:(BOOL)userSpeaker NS_SWIFT_NAME(setSpeaker(userSpeaker:)); + +/** +* 设置麦克风采集音量 +* +* - parameter volume 采集音量 0-100 +*/ +- (void)setAudioCaptureVolume:(NSInteger)voluem NS_SWIFT_NAME(setAudioCaptureVolume(volume:)); + +/** +* 设置播放音量 +* +* - parameter volume 播放音量 0-100 +*/ +- (void)setAudioPlayoutVolume:(NSInteger)volume NS_SWIFT_NAME(setAudioPlayoutVolume(volume:)); + +#pragma mark - 远端用户接口 +/** +* 静音某一个用户的声音 +* +* - parameter userID 用户id +* - parameter mute true : 静音,false : 解除静音 +*/ +- (void)muteRemoteAudio:(NSString *)userID mute:(BOOL)mute NS_SWIFT_NAME(muteRemoteAudio(userID:mute:)); + +/** +* 静音所有用户的声音 +* +* - parameter isMute true : 静音,false : 解除静音 +*/ +- (void)muteAllRemoteAudio:(BOOL)isMute NS_SWIFT_NAME(muteAllRemoteAudio(isMute:)); + +/** +* 音效控制相关 +*/ +- (TXAudioEffectManager * _Nullable)getAudioEffectManager; + +#pragma mark - 消息发送接口 +/** +* 在房间中广播文本消息,一般用于弹幕聊天 +* +* - parameter message 文本消息 +* - parameter callback 发送结果回调 +*/ +- (void)sendRoomTextMsg:(NSString *)message callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(sendRoomTextMsg(message:callback:)); + +/** +* 在房间中广播自定义(信令)消息,一般用于广播点赞和礼物消息 +* +* - parameter cmd 命令字,由开发者自定义,主要用于区分不同消息类型 +* - parameter message 文本消息 +* - parameter callback 发送结果回调 +*/ +- (void)sendRoomCustomMsg:(NSString *)cmd message:(NSString *)message callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(sendRoomCustomMsg(cmd:message:callback:)); + +#pragma mark - 邀请信令消息 + +/** +* 向用户发送邀请 +* +* - parameter cmd 业务自定义指令 +* - parameter userID 邀请的用户ID +* - parameter content 邀请的内容 +* - parameter callback 发送结果回调 +* - returns: inviteId 用于标识此次邀请ID +*/ +- (NSString *)sendInvitation:(NSString *)cmd + userID:(NSString *)userID + content:(NSString *)content + callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(sendInvitation(cmd:userID:content:callback:)); + +/** +* 接受邀请 +* +* - parameter identifier 邀请ID +* - parameter callback 接受操作的回调 +*/ +- (void)acceptInvitation:(NSString *)identifier callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(acceptInvitation(identifier:callback:)); + + +/** +* 拒绝邀请 +* - parameter identifier 邀请ID +* - parameter callback 接受操作的回调 +*/ +- (void)rejectInvitation:(NSString *)identifier callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(rejectInvitation(identifier:callback:)); + +/** +* 取消邀请 +* - parameter identifier 邀请ID +* - parameter callback 接受操作的回调 +*/ +- (void)cancelInvitation:(NSString *)identifier callback:(ActionCallback _Nullable)callback NS_SWIFT_NAME(cancelInvitation(identifier:callback:)); + +@end + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDef.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDef.h new file mode 100644 index 00000000..515ec9dd --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDef.h @@ -0,0 +1,68 @@ +// +// TRTCChatSalonDef.h +// TRTCChatSalonOCDemo +// +// Created by abyyxwang on 2020/6/30. +// Copyright © 2020 tencent. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface ChatSalonSeatInfo : NSObject +/// 【字段含义】座位是否被静音 +@property (nonatomic, assign) BOOL mute; +/// 【字段含义】存储userID +@property (nonatomic, strong) NSString *userID; + +@end + +@interface ChatSalonParam : NSObject +/// 【字段含义】房间名称 +@property (nonatomic, strong) NSString *roomName; +/// 【字段含义】房间封面图 +@property (nonatomic, strong) NSString *coverUrl; +/// 【字段含义】是否需要房主确认上麦 +@property (nonatomic, assign) BOOL needRequest; +/// 【字段含义】初始化的座位表,可以为nil +@property (nonatomic, strong) NSArray *seatInfoList; + + +@end + +@interface ChatSalonUserInfo : NSObject +/// 【字段含义】用户唯一标识 +@property (nonatomic, strong) NSString *userID; +/// 【字段含义】用户昵称 +@property (nonatomic, strong) NSString *userName; +/// 【字段含义】用户头像 +@property (nonatomic, strong) NSString *userAvatar; + +@end + +@interface ChatSalonInfo : NSObject +/// 【字段含义】房间唯一标识 +@property (nonatomic, assign) NSInteger roomID; +/// 【字段含义】房间名称 +@property (nonatomic, strong) NSString *roomName; +/// 【字段含义】房间封面图 +@property (nonatomic, strong) NSString *coverUrl; +/// 【字段含义】房主id +@property (nonatomic, strong) NSString *ownerId; +/// 【字段含义】房主昵称 +@property (nonatomic, strong) NSString *ownerName; +/// 【字段含义】房间人数 +@property (nonatomic, assign) NSInteger memberCount; +/// 【字段含义】是否需要房主确认上麦 +@property (nonatomic, assign) BOOL needRequest; + +-(instancetype)initWithRoomID:(NSInteger)roomID ownerId:(NSString *)ownerId memberCount:(NSInteger)memberCount; + +@end + +typedef void(^ActionCallback)(int code, NSString * _Nonnull message); +typedef void(^ChatSalonInfoCallback)(int code, NSString * _Nonnull message, NSArray * _Nonnull roomInfos); +typedef void(^ChatSalonUserListCallback)(int code, NSString * _Nonnull message, NSArray * _Nonnull userInfos); + +NS_ASSUME_NONNULL_END diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDelegate.h b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDelegate.h new file mode 100644 index 00000000..cba3efa1 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/model/TRTCChatSalonDelegate.h @@ -0,0 +1,140 @@ +// +// TRTCChatSalonDelegate.h +// TXLiteAVDemo +// +// Created by abyyxwang on 2020/7/8. +// Copyright © 2020 Tencent. All rights reserved. +// + +#ifndef TRTCChatSalonDelegate_h +#define TRTCChatSalonDelegate_h + +#import "TRTCChatSalonDef.h" + +NS_ASSUME_NONNULL_BEGIN + +@class TRTCVolumeInfo; + +@protocol TRTCChatSalonDelegate + +/// 组件出错信息,请务必监听并处理 +/// @param code 错误码 +/// @param message 错误信息 +- (void)onError:(int)code + message:(NSString*)message +NS_SWIFT_NAME(onError(code:message:)); + +/// 组件告警信息 +/// @param code 警告码 +/// @param message 警告信息 +- (void)onWarning:(int)code + message:(NSString *)message +NS_SWIFT_NAME(onWarning(code:message:)); + +/// 组件log信息 +/// @param message 信息 +- (void)onDebugLog:(NSString *)message +NS_SWIFT_NAME(onDebugLog(message:)); + +/// 房间被销毁,当主播调用destroyRoom后,观众会收到该回调 +/// @param message 销毁信息 +- (void)onRoomDestroy:(NSString *)message +NS_SWIFT_NAME(onRoomDestroy(message:)); + +/// 房间信息改变的通知 +/// @param roomInfo 房间信息 +- (void)onRoomInfoChange:(ChatSalonInfo *)roomInfo +NS_SWIFT_NAME(onRoomInfoChange(roomInfo:)); + +/// 进入房间后,当前房间主播信息回调 +/// @param seatInfoList 座位列表信息 +- (void)onEnterRoomSeatListNotify:(NSArray *)seatInfoList +NS_SWIFT_NAME(onEnterRoomSeatListNotify(seatInfoList:)); + +/// 有成员上麦(主动上麦/主播抱人上麦) +/// @param user 用户信息 +- (void)onAnchorEnterSeat:(ChatSalonUserInfo *)user +NS_SWIFT_NAME(onAnchorEnterSeat(user:)); + +/// 有成员下麦(主动下麦/主播踢人下麦) +/// @param user 用户信息 +- (void)onAnchorLeaveSeat:(ChatSalonUserInfo *)user +NS_SWIFT_NAME(onAnchorLeaveSeat(user:)); + +/// 主播禁麦 +/// @param isMute 静音状态 +- (void)onSeatMute:(NSString *)userID + isMute:(BOOL)isMute +NS_SWIFT_NAME(onSeatMute(userID:isMute:)); + +/// 观众进入房间 +/// @param userInfo 观众信息 +- (void)onAudienceEnter:(ChatSalonUserInfo *)userInfo +NS_SWIFT_NAME(onAudienceEnter(userInfo:)); + +/// 观众离开房间 +/// @param userInfo 观众信息 +- (void)onAudienceExit:(ChatSalonUserInfo *)userInfo +NS_SWIFT_NAME(onAudienceExit(userInfo:)); + +/// 上麦成员的音量变化 +/// @param userVolumes 各个用户音量信息 +/// @param totalVolume 整体音量信息 +- (void)onUserVolumeUpdate:(NSArray *)userVolumes totalVolume:(NSInteger)totalVolume +NS_SWIFT_NAME(onUserVolumeUpdate(userVolumes:totalVolume:)); + +/// 收到文本消息 +/// @param message 消息内容 +/// @param userInfo 消息发送方信息 +- (void)onRecvRoomTextMsg:(NSString *)message + userInfo:(ChatSalonUserInfo *)userInfo +NS_SWIFT_NAME(onRecvRoomTextMsg(message:userInfo:)); + +/// 收到自定义消息 +/// @param cmd 信令 +/// @param message 消息内容 +/// @param userInfo 发送方信息 +- (void)onRecvRoomCustomMsg:(NSString *)cmd + message:(NSString *)message + userInfo:(ChatSalonUserInfo *)userInfo +NS_SWIFT_NAME(onRecvRoomCustomMsg(cmd:message:userInfo:)); + +/// 收到新的邀请请求 +/// @param identifier 目标用户ID +/// @param inviter 邀请者ID +/// @param cmd 信令 +/// @param content 内容 +- (void)onReceiveNewInvitation:(NSString *)identifier + inviter:(NSString *)inviter + cmd:(NSString *)cmd + content:(NSString *)content +NS_SWIFT_NAME(onReceiveNewInvitation(identifier:inviter:cmd:content:)); + +/// 被邀请者接受邀请 +/// @param identifier 目标用户ID +/// @param invitee 邀请者ID +- (void)onInviteeAccepted:(NSString *)identifier + invitee:(NSString *)invitee +NS_SWIFT_NAME(onInviteeAccepted(identifier:invitee:)); + +/// 被邀请者拒绝邀请 +/// @param identifier 目标用户ID +/// @param invitee 邀请者ID +- (void)onInviteeRejected:(NSString *)identifier + invitee:(NSString *)invitee +NS_SWIFT_NAME(onInviteeRejected(identifier:invitee:)); + +/// 邀请人取消邀请 +/// @param identifier 目标用户ID +/// @param invitee 邀请者ID +- (void)onInvitationCancelled:(NSString *)identifier + invitee:(NSString *)invitee NS_SWIFT_NAME(onInvitationCancelled(identifier:invitee:)); + +@end + +NS_ASSUME_NONNULL_END + + +#endif /* TRTCChatSalonDelegate_h */ + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/NetworkRoomManager/TRTCChatSalonManager.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/NetworkRoomManager/TRTCChatSalonManager.swift new file mode 100644 index 00000000..50c40331 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/NetworkRoomManager/TRTCChatSalonManager.swift @@ -0,0 +1,112 @@ +// +// TRTCChatSalonManager.swift +// TXLiteAVDemo +// +// Created by abyyxwang on 2020/6/12. +// Copyright © 2020 Tencent. All rights reserved. +// + +import UIKit +import Alamofire + +let chatSalonBaseUrl = "https://service-c2zjvuxa-1252463788.gz.apigw.tencentcs.com/release/forTest" + +//roomModel +@objc class ChatSalonCommonModel: NSObject, Codable { + @objc var errorCode: Int32 = -1 + @objc var errorMessage: String = "" +} + +@objc class ChatSalonInfoModel: NSObject, Codable { + @objc var appId: String = "" + @objc var type: String = "" + @objc var roomId: String = "" + @objc var id: UInt32 = 0 + @objc var createTime: String = "" +} + +//roomListModel +@objc class ChatSalonInfoResultModel: NSObject, Codable { + @objc var errorCode: Int32 = -1 + @objc var errorMessage: String = "" + @objc var data: [ChatSalonInfoModel] = [] +} + +@objc public class TRTCChatSalonManager: NSObject { + @objc public static let shared = TRTCChatSalonManager() + private override init() {} + + @objc public func createRoom(sdkAppID: Int32, roomID: String, + success: @escaping ()->Void, + failed: @escaping (_ code: Int32, _ error: String)-> Void) { + let params = ["method":"createRoom", "appId":String(sdkAppID), + "type":"chatSalon", "roomId":roomID] as [String : Any] + Alamofire.request(chatSalonBaseUrl, method: .post, parameters: params).responseJSON {(data) in + if let respData = data.data, respData.count > 0 { + let decoder = JSONDecoder() + guard let result = try? decoder.decode(ChatSalonCommonModel.self, from: respData) else { + failed(-1, "ChatSalonCommonModel decode失败") + fatalError("ChatSalonCommonModel decode失败") + } + if result.errorCode == 0 { + success() + } else { + failed(result.errorCode, result.errorMessage) + } + } else { + failed(-1,"返回空") + } + } + } + + @objc public func destroyRoom(sdkAppID: Int32, roomID: String, + success: @escaping ()->Void, + failed: @escaping (_ code: Int32, _ error: String)-> Void) { + let params = ["method":"destroyRoom", "appId":String(sdkAppID), + "type":"chatSalon", "roomId":roomID] as [String : Any] + Alamofire.request(chatSalonBaseUrl, method: .post, parameters: params).responseJSON {(data) in + if let respData = data.data, respData.count > 0 { + let decoder = JSONDecoder() + guard let result = try? decoder.decode(ChatSalonCommonModel.self, from: respData) else { + failed(-1, "ChatSalonCommonModel decode失败") + fatalError("ChatSalonCommonModel decode失败") + } + if result.errorCode == 0 { + success() + } else { + failed(result.errorCode, result.errorMessage) + } + } else { + failed(-1,"返回空") + } + } + } + + @objc public func getRoomList(sdkAppID: Int32, + success: @escaping (_ roomIDs:[String])->Void, + failed: @escaping (_ code: Int32, _ error: String)-> Void) { + let params = ["method":"getRoomList", "appId":String(sdkAppID), + "type":"chatSalon"] as [String : Any] + Alamofire.request(chatSalonBaseUrl, method: .post, parameters: params).responseJSON {(data) in + if let respData = data.data, respData.count > 0 { + let decoder = JSONDecoder() + guard let result = try? decoder.decode(ChatSalonInfoResultModel.self, from: respData) else { + failed(-1, "ChatSalonInfoResultModel decode失败") + fatalError("ChatSalonInfoResultModel decode失败") + } + if result.errorCode == 0 { + var roomIDs: [String] = [] + for roomInfo in result.data { + roomIDs.append(roomInfo.roomId) + } + success(roomIDs) + } else { + failed(result.errorCode, result.errorMessage) + } + } else { + failed(-1,"返回空") + } + } + } +} + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/AppIcon.appiconset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..9221b9bb --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/Contents.json new file mode 100644 index 00000000..51c5dadc --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "navigationbar_back.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "navigationbar_back@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "navigationbar_back@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/navigationbar_back.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/navigationbar_back.imageset/navigationbar_back.png new file mode 100644 index 0000000000000000000000000000000000000000..4d4b18a97d595c7957bc97dec18ebf0a9da97292 GIT binary patch literal 290 zcmV+-0p0$IP)Px#+(|@1R7efoRLc#*FboZ!71)An=O}mP;Q$jbLq}qTwtz%ZiC)Zeq*N8j!Hz(s zSW4}>@A;QB#=J{yiP*Q~$HJI9>l_Jz25w{NHoT+^FfJ*7+SfQLqc16^?*zzwgbog{ zs$l2o2hm2v|4)0@?kEP)Px$;7LS5RA>e5SxZjCFc7s72&u3D@maHC1BYP4$+!V4t^j+sZ~?mH5VQ>-)JRlF z3^O4krTKO2OsI)mDRMsZdGFO3e`1W}H=P4i?BqAuwbn!Qkc~XsX$nt`uB{Iny}Tc^ zicpLyG2AFR(76{G%H-u(&c4QL4;7m%( zN)0J6+8&er(XJKytu*uv%)lEHbPe2?00U1*1u}4vf&-S@N|8L=F(+))Yu)2_6&dwg zV27EA|D)IrPywoHmj?%W@o+S{Qq52bejS5n3Pf3IJHqP%&a?Xe+ZAiL%<^hjvM}UFgzQFClwteR7;My9+c@nNa^U-7sHAC= zFGVK2THqE}$YH;nAD?iFU@O3r6mB#H>KdzYuapAQ9$k`}d;F4iv6RS~@z%&(?pgb` zbbk#OtppfP$V5a0LMGxwAVeZw1VSRxi9iTMR0xDXgfXbJRJDrRGKIlUcY9a`ZA%a) oLSI?&Tz&1)k~%($3P=_B0gs>WJVcPx&lSxEDRCodHo4<3@Fcin7(jQ#IQOKn`6RgnxfICJ8MvlGAF!ERM2T+cc|9}D5 zS)e;JbZL?T*Mt)8D)d60qd1l=S-)cEd66YOJ$?0wV#)S1W5JHob0JEdI~i=0x-P1$ z><$|l8)5^u^oI~P^BxvP2L^vfY?wF7@?cOZ`lk@xQUi2lWCX_k4N-#klvjCF`R-ri zT6=AUsRIdQi!d8cMZ*YEQ(_Xc85~K=2r*Lt1 zxdzn|6ha6N$VyO1Ay$H72r&{AQ%I>GxCfey*Z_?nb)BrLud?%OrB;phI3I3ou;*&o zV9dU$`DEv~2*FOk+it+eXh@hXMIu&*7~NLdQX_jJ&}ahkj`z*V4B&JmK2H~4nYxN9 z+Ma86ck&Ok)W8O zj0MFKWhE$vC~HBXMb#1%QdDh0p+q?e3L(l_kSa>XtxS3yz5`{+54o$nNG^f|5CI}U z1c(3;AOdp&@Jc>=>?5D-LVjMG=FH1h$W{6@R$=BF%0sa3Dpt$kzo(wlFt_ok8WCkIa!Wn~O=InKEmmRu9MWHK~G%BDbfkCKI z02zWgk~8LM>KTJzFbxW*$zXy4Y6F-cfZ7DcE1))l@dBvLV4MI=gJZ|+eZ@XzC08XJ zxM^y&ip{`$lwj^^JK(GpU~qg!fP@g+{W1F_!Q8`!1?gKEV*O;*_Av!It%{7|spOz1 z`yGCe5An|R^cX_Ee_e>%x$;J5jb>1Ogb=5EdC6Yp%P}usaGY#kVfSOb*vEcDq_qH{ zkaYm%1ZW*Vc>&aBP+kGG5mXRBZ2}b(P#Zu+0n}trQ2{j(R1!c<0+key2`C6VlJ`T8 zx*h%w?bkL{Ked!!6aAr&2sKmT?6@uS`qjMz0Qg`khyET00000NkvXX Hu0mjf9w4;k literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/Contents.json new file mode 100644 index 00000000..8daa9228 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_audioEffect_close.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_audioEffect_close@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_audioEffect_close@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close.png new file mode 100644 index 0000000000000000000000000000000000000000..865ab3b2a3694f9a1748ccb25dd1d521d1579047 GIT binary patch literal 1095 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close@3x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_audioEffect_close.imageset/voiceroom_audioEffect_close@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..ab6577813fb9c4b298958083e9c8279acee63b63 GIT binary patch literal 4101 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

SFsW!QRwDZ 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

dQ$N-}DEb0@!7cB=4TBMbe>o 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

K$%4_5qEmV)Gq*R(r3>Qb`dZZ0Jaj3 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 z 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 Z{|9%2pWNVv{!Rb@002ovPDHLkV1h=x!QcP@ literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/Contents.json new file mode 100644 index 00000000..4a2f485b --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "avatar2_100.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/avatar2_100.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_cover3.imageset/avatar2_100.png new file mode 100644 index 0000000000000000000000000000000000000000..d446561cec0b9432b78e24eac11cba7d449d6edc GIT binary patch literal 86943 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�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

jg6I4bV*qm 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/Contents.json new file mode 100644 index 00000000..b54cef6f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_like_normal.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_like_normal@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_like_normal@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..fbc6cc5dd4c4062f6c84e67301eef868e2e13fd6 GIT binary patch literal 863 zcmV-l1EBngP)Px&8A(JzR7ef&Ry|As@dtss+i_=M)_r@s+>soG(QW3dhW6bFZg`?LP07ol`5Q@aE(%P^FONwkd{5pVW3P&$<&Xs`QdqZuG#I7*TWisjq z;_*T`>f#w%w~AQ9=o1(A1bHRwwmoL}S=V+{TZ2+_0iUObW;N#X+>}783fJaz?SKh7 zwU660hdHK?@W)*85-Obb&vLgoy4)7CN{0 zwBI{#9Fld$&t~9Du)4`N#EN;&B#x^?d_$HXU1XRsd_{~Gjr?pd*{)*}<2>a!yLC++kETz}-@shJx1neu4@4(lhRkOQoM zP-obB;zjVpkwtrBqpxPm6Fk+#AXUi~Rsg_Og~mVgA|=vNSNYM-Pb)k;G2Na@@uPO4 z-3QKR8L$uf->Oz`s@#s-eNfO0E&n3_4q7sUc#m~^5gKA%MhJwW3R$&qi pO->fEwS8Um`C1pd`u>_r;cw+52?(Xs{+j>*002ovPDHLkV1hoXmE`~c literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..aea2dcd3b9e49a70834bc906d57bd83c54dbe65c GIT binary patch literal 1786 zcmVPx*v`IukRA>e5TVHGxMHru%-McFVn-Ek&lhWQ{5rR@Ir3IoPg=H1 zKB#X-QA1RWz8M~TP#=r|1gjDg1HHD;5Dm}+sz9&^a(8W|fMTjepm(>sba-k)o~>vBBvM zl(vL2jn&mH;*=y^=P{*oh)N;!F*m1&E&7_T3D~3w(vD>hPd^WR%V01<5)VONHrDyi zfc|cl>4I%Lcg{C!NPbl)#zA)Z4)Q(}j<+?8Pd~n(>TBLk2a68e;Pff=(cO>M1b)$P zlJ>)~=bW6)w(AMJj_dSbDxos7gPXn{9IE$kbK?v?L_(K%JAH3sf|6j&B!lz)`n{bF zZmRRYk0@3$1&UvwbTAKUZm4>XQmWb|5CgeS`cjDj9Y>>^DaDegGY4{;0U4Z|76i6Z zL^bGJ1%l01wnbtu+Zv08TUi0iI|K&s?UCrzQb`JFRGm&F@)x^vj|Us74ujn+J9~ed zqW!J5AW561QIzn>Wp^CJIed(Zt@CJzn2V(m1lr3haM z)mME48Ut`Ra-jmF_#oCaWt;BG6YLg);@!Mdt0RioDP#5|xw znRzP1H5PMsMq;nAXO~CR<=R$N^!f5d{`D`k#1|t( z>ky^)5F!m+SJm*73j>#}{4Ieyj>cEBsr?+Q0G60G*9YDaZS99*OOT9~h&r)-X0r0Z zOV!m0Q8xxSd@TMV*66*WlT}-pT=rp0^_1bZBe6|{pb9G=QD+7>0CydW%}Qx#tr(Ec zwm1auRLwIIHvV-+`sF*xzHcK#*+{j8+}D9>ff7=XG?4?K{%rfh(| z8_5@~LJfhfPQJE`A*gXq#jpI81p1kz8&IAjBVz#izW4mh8&}DC=vzs*pgcAsV*q$; z_KdUq-3a<-iE-xgiZQMkLr~Yr!C9%1gyA=vF9U|^1Mh;58|j)cBx{^oenvw?UwG!a zTtFdLPVxt~gTR?&?nkRYhpkB>32=1ViFCV zy&?NLpQtOp;^YUmy*(H2^C}}t*|vbYqbe9(CWv&{o_T@9|4Ubd4-E`Vxb}N$BUSM< zQ+#$^LV6EfoxW#Fqj8scOBaBTf4ZcCW$jMsqEc$JEx&NGkQmN2EL#OyrY`c@ol z31cetk2iwm@mg`PCG3$s`^*W(TVL^d+stFOCEUm+3j9Q&Ibgi>Jrm`fEw$7BFpt;q zXNfz9Pn?)YlVvXun%jvwGhm_n8b-s|JN!wgrskRzRz|`Qw7+MtQc)5cSU_G*f;E@#PzN~L7Ccsx6sTsKV^!1yjj@}JbY zLJ{Zd{N72P-F#C5FmsW4BMji3Kb@bcCh*hwBF>3QKH3_b=X?+h@H5H069z#3zb0xD ztudc%274ySH&IF^(N@0MlF2t4d%+09Aozibq(;}+ovH&rkbDot<3p`(PufA8TUl_z zFp!SpgR?btWVIb}PSjgc@)h4if|x?cTSgcL-xld(CzI4wK%5g*W$Bxi+RC57rzndR c$h`vp0`n|C4q9j7@Bjb+07*qoM6N<$f>1A6t^fc4 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@3x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_normal.imageset/voiceroom_like_normal@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5c5c9445838a9802f7eb7e0deb8cd3d277b1f6 GIT binary patch literal 2644 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/voiceroom_like_selected@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_like_selected.imageset/voiceroom_like_selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bec3351dae6cefa2cf6da5ec992b03bfcf775d0c GIT binary patch literal 1731 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/voiceroom_message_select@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_message_select.imageset/voiceroom_message_select@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f43ccfce03ffa0f3659a177195dc9ea65e9f58ec GIT binary patch literal 2120 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 X{+SE1mAo%R00000NkvXXu0mjfFpmqo literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/voiceroom_mic_close@3x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_mic_close.imageset/voiceroom_mic_close@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c388bff94da128f5314036f76cdc7fa5093caa48 GIT binary patch literal 3423 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/Contents.json new file mode 100644 index 00000000..7eaae675 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_oval.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_oval@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_oval@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/voiceroom_oval.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_oval.imageset/voiceroom_oval.png new file mode 100644 index 0000000000000000000000000000000000000000..3f52551b391af074dd723540ada3d2c3d15bdb25 GIT binary patch literal 590 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/Contents.json new file mode 100644 index 00000000..e336bed1 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_placeholder_avatar.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_placeholder_avatar@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_placeholder_avatar@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/voiceroom_placeholder_avatar.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_placeholder_avatar.imageset/voiceroom_placeholder_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..7efbff89e93852ba55ae74dd133022c82583b5a7 GIT binary patch literal 3818 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/Contents.json new file mode 100644 index 00000000..5ad581b9 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_selected.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_selected@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_selected@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..4dc72c9de89e2a122e19e263e6eea3cf65584d02 GIT binary patch literal 562 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VV{wqX6T`Z5GB1G~m(&Q)G+$o^ zEg+kNfw4W4fd!-lh^2s-fq{7eBLg##W(0{XV1mnvEMP{kK?*nB{qPs4Y>uakV~B;| z)~S2F4hM)F|NniNtcxs*b;M@QuEiIwhEE9lz$$WAM!QdTYM+(n4-Tms*6U4+LkhY} zSIq8m_FVV9{_{~nFReZ_fmtZr2Och9z5m)NF*iwntw2TNmRmd4-S1t!czNHXg1g2)GTc`=m3Qjp{1%aY zczK_Y_0-0TGuaDb*ZKVrZaHIM`+i#2rKHH+Jn;ua4%E(?x%rB{uD-{coU;#~J=DHv zw0zp$NW-ghLK}|owpboF%~=!DYt}Ytp|vyH+KHcLZ1Oq$D_{AJeO>w*(Z*%xjie{{ zM@D>3>iF&-d}GSSjEsakTRtB9_iYcSZjeZ`?6|){vhP6S?e?J8 zf~MRH=CLN6`*gU+=4)(6x|r+!*_{UZB`OUI4jD8D*oqzXEI8P8;aVz#ZpkJIg*hvG zW22{7NuOAm=HnrjnCxxbWMNvA^5da+^Tp{rw&$9(idhP?rilJ(OV-Jh?pt7VA)}_X j{pWGU*?iym=Qqf^u03IOEbi-GP<(m1`njxgN@xNArx)aY literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_selected.imageset/voiceroom_selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..83787af2abfbe2681dcf7f793354522b40a1e92e GIT binary patch literal 1041 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 LNkvXXu0mjfNvoYa literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/Contents.json new file mode 100644 index 00000000..1a961815 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "voiceroom_voice_close.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "voiceroom_voice_close@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "voiceroom_voice_close@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close.png new file mode 100644 index 0000000000000000000000000000000000000000..80ece84e6fbaa8ca9ab604fb83740e0fb484f1b5 GIT binary patch literal 1041 zcmV+s1n&EZP)Px&%Sl8*R7efgS6gTkK@^>t-OZydq-sU1Nh5;d3n{gwqJn6nXaxn)s-Pe~KvaBz z{wPueKSf0l{3w3-;{*LuOxsmNe5I+PqJ9)@HYti|t9{xg*%{|<9Xo3_ZN!Q?kiB=# zea+svcXoo1(+EF~9Ra-IO^1&FqbOJbs!kcx3l!;3-UTft>!UGh91}t;PeSFvEV}ypv0(I6pEmV4VUE~^~bdm&pXBoqp;BO;C3mjUk zDuWQAp~=_}NzkLQvW!(Ptq7h5CCbo>3}HAD+XX_kh@Av#4cUF8L*|6uAEdV;#y)u& z*+TuaiOy&>w}pqG>Jh1OP& za7xp7BEq;6=C(@FBeD66;E+%h%M1jo8!A>EE{jzs&G?$HtIDU4eK8p>%tLZuk6S&hRniG!EB8z6nrf| zGnQ2buM&(EzFmt1Zi_5Hnd-0J1s68Qk3t@nR+O9~gye2qHM7_-HGG{tiEovi0zYD8 zP%`rdS}4Uuz{?{iV^^oPjUaYcHUxe|V<=VL0eDG8@cx}gZGO{arf_0wjC!7N*_+%L z&{=_Ya=2q|$%z__EeEnLTE@>qYNCGOS*FEZT}rK&hzIw~;l+i@)pK$flbMK4M_Fg_x<-dXhq(!5hKIZf~}*Gt7R-V8@!>~>Di1F6XkjHFE5-vz8iuxJ~yVIB-(^1N_FJ-oP=+s2ySae0sbnj zo;r0v^LAaLDV*Qm(|6!@G*JmYLUV#|3D$1#!$vFYEvS+Gj!Ix~xR~#ydptc4Jf(CA zP#B*)pI-pwhkXf9F-9#gIMljaL7*m~Ux32!rQL-UsXQ2Z_Xm0lz=B7~?cJh8vr&w_qnBs1PaW zVO41$0=O7Is#*XtwZ8C_t`>hWWSLymG7h{RHP-Q-pTYCnlhoW7tIH;S{8?w%z(N`B zCh2Z-lS+_JV8aC#I>XVNQXQJ%Z|6?Vz-_{eCf4$OoHm@(e_HkpOk8t+j%3Gp00000 LNkvXXu0mjf>}ltV literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0b4b592cf8247a3059e0049b2566f6b88b105c9c GIT binary patch literal 2288 zcmVPx-s!2paRA>e58*6MFM|oyvZP%ocX&R|*V*AdmC_-ssCvhAI0_6B?m$p$!A*D2J z!;gwTt%MNbAxcrz(m(v+R|Nv03Vxv=5LD2{zPnfvU}5{tiSwWhQk#3YjzXX)XvQ@Q6<9)Sjes~YAi5vpIr zO+>H_KqvZRFQ%q*2kXLuiWh`1h(YhEt4z-3zW)NHT$b0+8d1%IfK#!0$oNeD(`qxk zJlmrjL=X*NR{>qu8z`hhbYS;!bs_{-){Oy8Rc3lRw?`N>fjsbnIKb4K^S6_$)-yU^ zm9cSbW?e;dGlDeRwYP&PLg;nMUWyZco9`Ug7JA?rHu%ZTd8tf}&gGxl+Z+3pt7m;A zCWLTS^N1XGUM6vrscSY?ARMH$^4`wwm)*iyRvC;uN~wj$1Q8rs19TweV<(GSi6I0i zP(lr8O&c(bqYl(w=x~rtp|&<^N`d5H*7oCJ1|y1yxMXF2n>cA0pWTk$dEeLG|3^ z0y(zFjEZ}uQ#Tu~JlHv418}XBOkc-v;9!h0LhQxlWy6(UF)Lq{>%gA+Zd2YFD}6D! zT2q+1F^I6j_<`YF-9JXL!$PnP*@Asq(&cLwBPxV}(5-@s^$fQ<_s>VZY( z7#zW#43JXM3(&7b>e$bbUgtZxbYVX_l`U?QkAW|M3~T2(~*NTVyI*c;2BU;^$bE^TLC5wVbAj>J|wXC-rXRWq6Ih)&rq>Aeote zFqERA)bN&>KAwA;5^JYoBNQ5JIaN)MPvyTY&w;mu@}wyRb`1BBhPy{|rjpCr!mG%# zf~r-Cr%t?mug0n&eeJ>B*2)&XSECVtNN3J{hg8hR#xlj-UgDmP$7Txm!G+pO(T{I& zG6waG@KM{2i?B1s`q3oJ0T1nu4D_6M{Z!%o)(^x%M(wB6X{L?#UZOACPNv`aEI=r2w-`qOwzP^J0I@{o7!0}xYpyz>px##b42l{b&{+6#BI)owk@Q(NoRi}V^ zcD0=bw8#xzAqbtE$vp>7LDtPF@I4(v<;d>Xk0=uhfHzVsL4ObOe!b$^)v6;nRq6*k zKclLy7w#J|Dh>B{{z*nrcjLqQFffo~Fg&`e`!rd{UJ2tQ5*!Yb?bi?xw z9LsJR3cEDJ28;nfYK52h0eKs0L!MkfC2FysCw6!K8+l%^F5vnsmzQcdevp7CrqA8k zc9(f+PgmDZ%SCTkpQWO6IF7Pn6k#!)MOe83~n-cvA%oX|SQ*&Z8s!@s|ui(%4AKXgjwq zKRa10wj&QAyd$TEaAp9dlyzKNSGT#Ld{YICjRLrLSM0BCElX({_$=bedHzLJ261Cu zs}nHr7$={=IvqA`z|he1=H=sRgXLS?n4IlP>$O@5Z^v;N*ephGg- zv(HSiU%tz*@n0hC2AgJtv2pN5LE^4!6=mRr zC2kl`%V3?I7~YkR4#a=zwyB{WKxN{qY=0at_=}$m`pfFILC(^;4$@vXG%gP*Bl5Y8 za(*z>2;13lLQZ1}XEi=+f~n3)X}`g!^JL-7$c*%LzOme>svQt&gjEB8t4TV&PN!Eg z!e9#mZ*4Pf-P_wWrP~fdM-s5=2>u>n$-hT9!=P45e5CYvBK><^KZIj6;0ugH?tA0000< KMNUMnLSTYEdSf{N literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@3x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_close.imageset/voiceroom_voice_close@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..c3f1808fa9f7e61dfc906ceb5d616868f01c7333 GIT binary patch literal 3559 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/voiceroom_voice_open@3x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chat_salon/voiceroom_voice_open.imageset/voiceroom_voice_open@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..52ef5032088f3ad2a38cfb168ad8bb04705fb8b2 GIT binary patch literal 3614 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/Contents.json new file mode 100644 index 00000000..9c1a119f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_add_mic.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_add_mic@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic.png new file mode 100644 index 0000000000000000000000000000000000000000..c605f8ec785d53bee6dcd1e134a03907f6ca2407 GIT binary patch literal 2259 zcmZ`)3p~?%8~<%C)6{W2opPA9q6;>*E;idj!(6t6GztyF7@KV!lXP*ZsaT>?tP-aS zB_gL#q(!CU*C}PI{&4&df)S&-~aRbKhN)ZzTfA0e$Vs&eEu2UOt(2m z6C?m&jys*^14%NpQ99btTacH$7806~P7EgiDrCBoY%S=F4x{@p0N82?z|J%PCLq(! z7XWOr1z=<|0Hizseh?JYtWyW#aaisV3P3gP8aE^1C*fZZ@a$PyBy#&X1Lv?P`nCn8BGm`?~2q^r$14Ehs997Dmd z7~beLd?5$D5^IaK#ZZxGG@2|7k0ANbTtCyH69p3`77Iu?TtY$uHi3ZU3nOuML?RJq zi^t*dHW0!_lo%&wOKjpq3ul7-Ck~Ax3KMb#VlF=pt&YnMo%gOR+s5)Lnb#*O8~iJ;P`D{aZ2 zvi!~Qwa#ydtgl2n{C_dO@%%4y4WGvs`U==#9ID;tWZ#&+L95Fqtrc=PP)F5$Q^Wse z`-~^!)J^@S$ukrDWQ9gZMUrt}J_jl?WPw!`09v{3G$%jStVgUMo}Y{Hv@$NC=aG#~ z`eEl;v9UUEpL6M_qGb`t z(Q_Bh&1FfWvf;X&=H1Hbo~f6Ad^lZudU;S~JpbGOR*Vpi0 zIm~)W1nIo~?8d}~toPrW*F`fP*A6}kuTXJn9pJ3;@yJXo#ZoW-3O%Lrwq>bA)vdp| z<&p-ktOAr8y)SMh#zw}ly=XR>EEc%1FHj#`;tkYJs&n*nz%ykKtoj!N5;z5CtOd>B{S5bbcEYPw= zVtiD?&JW>%2+OUoo?brd83Xe7{d&cBtIPY3atihCiaXMgBl>r}^}9-!*A!&I=XL_N z_WXRCJNo^qiCS#(7(;M%7#?7XNK{x^$UTCxV239Ny}_F@f^N13=siZaNkUglx$Rw9tW8`#uqH008L5h6j?Pix-&YCST zeebkpXPt@c%{nVrjNf1XZxt!BspRb>D`-r=yJ!I|M>vt~E=oA^+lo5G^du_M@Y-wE zIDIf`r~sBUd^kuW{@y545wmXt=0uzvJA0M&cEfS&@Ac%dis_=vJk(j*Vgi4W!J3R( zP;XF0-*E8I-eGaQRhul}F@DtI)QhJkoYar$o-K!TS=!S~T^?`Jcx`g67UKx>M>K!A zvS~u~6T8EF&#n~VVS@%)+e-0hLVxw8qn$rpHK2%-cA1@QDS>7bd&Bi+d)JfH{!N5b zR4x(hzjA)NFpDkU3XAP_wc=mDFa51mNn7-LOxg}%AEK^9ctF{kf^RBxbD@#b`hUo8 z^IqR#J=lCYEa|@I*p_%EBRO+d*%R-87|G?PW}dv%!Sh@}P+-1JmFd;)jnY9!v(~hf zCDAcA{A7BM9vT}P(4`Mwn$jCjgkuXjw^LJ3qQnjH$Mm;Q2{lp%{&KJb@R59sT^ za(t<=(O~a;lgFSV>VlDCtZxM~ZFieRvR+6Z<@~Zcs_)8CC~H>*+R12s`-N=|fkY0q z8W)7v_vXXE@WMYQg*hqnW&YL;Z;77l_RA+$*O}G!Yqz!m(!4= znkAO2RL|RAxBHng7rYQv#91#bY5bsj+%fqUPpF$ky#g3F2$JD56#H(`@nGM3W6z5T zWw)=HA?{H!M|?t_x?y%5xAt88A@R&*{NZ*c~7%%DtGH9(;n`MN-YLa;teWc&li)TiwU%j{C`# z!$So>R~q0AWrp(&DJ=iX0QWCkv)_&k?nsQ6Xm@1sE#m&ny`GUpGA7BZ=Rr+!p2Dhy z$yu~-&@W!NcS{wunuFZO3*WCGEW=U`p6m;&3D504#wu@6_W6=JQQCPiDP#wndYzsp^_rLdz^p4_GT+fxF6$Cdvr7z3`Nc1EhFpv` flFY|nAF7Al)}3OLuIX8+f8p*fOj?=q=9Iqx=$Dcn literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_add_mic.imageset/chatsalon_add_mic@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb93165573efe23f7dad935bc3a4ab9ee0847e8 GIT binary patch literal 2285 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/Contents.json new file mode 100644 index 00000000..0c508c82 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_anchor@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_anchor@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@1x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..9697f067e1eade259e098e97385e6e86c72e37d0 GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uuz(rC1}QWNE&K$eet5b#hFA#h zonXlA7$|bwc5=(Zr9P+F12+9)Dw}^G$56v;a%`ApGtad2O&ao!n-Wr|Nr-emFaNS` z-S4W8V$1917Qg%Z|9s_lSEc`4*Gr`f8iaWiK7P(S5^9hvlh%;D>*e`GHW5Re9>vr1 z*%Bsg?^j??jcEMSe(5@6$D{(5PU{jy-j(aq1Ql|crPNuc)I$ztaD0e0sx89jS>I= literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_anchor.imageset/chatsalon_anchor@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a9bea10d10156ad17ddbff3c280df705dec878c1 GIT binary patch literal 744 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz07Sip>6gA}f5OZv>fz!c=^;usRa z`F5JGhiIV4aaqy*9S58WpF2%B!QnDVK&8d(m0y8iNB5#>Z&@-gDi!^FaP?HL(z_#3 zPn<3|nAbJr;ZWBC*CpJXzpDQF-PJb!{Orz5^ZYxN503BsUi0Vt+{*H2zOF}i z&OIorA;M+*L5S~xcFtkt47=tsN6%R{>}Tx+Uhssa>~Q+C@!HMj_G$N~B;NiX)DhPr z9It%cB;7n9Q(dy>Z-$A=70C^ik$DfAM12k7wpm8zB}iVZ)Rr;c*WbCE|MTJd4WZW= z6}}nNws&~3q${vb&zVtazo&6S?n95Nur+h+l*(lP&Cql2c^sfG+B4OFt6gCm&rQ1~ zj(tK;C)6g@@~=AMmNoPK6@BGYmWz1>H}wuWPOsVNf3U@S&W+F=LX#)!otb*KD0Ww; zu3=TD^#mKX>I>rGF6X3nyx~4L&0?;@oF=}-Gx%AYxQm_$c5l9XJ$Hr82A=tiVZwi9 zPkhpSp|$0BdR=d^p8M-E5KHs=jttHb|_+%;P@IZCLoa^s1` zOK);EmMoulD06Yu*^P~YYd3$qe?2StFUOn13#WOkk$NKSzgavgSIK_W{X|!9wQmlu zd*b(fmD+mCrH*Ca!LSgcy2|PGEgHXDH=D0ory{Sk{vo@_-{^Pty)!lWz|kg`ESR5|v1p+}b$4V+;FNExx9vVYQBIVF zyX*h^sxzCzss%mQTz^>3q=5Um=cF|=t}eLIV65@y@Ycm;j&aIWtUV%n3k_O* z<*&RmX*;{*9=C9^j(830$Fzy*!YSTjNz(5gtVwanUd{ejxAwWn4I>n&J6>tjZJfs!&?<*5g$8-56P za91=PvJ0E0c3w^IW~<46uIs6gA}f5OZv>fz{KR~;usRa z`F84lFJ?!9W5rrZDhW^bJ2?tiON+jC*zi%5#k$)h^K#TLo+kf<{ORr;*OC^lU~v&_ zQs7AX<6E?N@%GubkLbF{{@7H#`TqB_Dev>v2mE+Fk!Kg z^Zay3!d_z!AKwAn53OrB(`}>JXZSWdf8cU*-mz%rx$GtHbq^$nHYXc=KKi2Rwb~B9 z&qdl#w&^UpZgt1#=A&(MGL$NoRIu7GNxR47{P0QP`%q=1qsGPP%Vg5~Kq^96lZrM_sZ@cR$L00&f5e^?t>jq5 z`eu!Y$Z0Lv&UA_FC>v|rivlGtG?5{f6$o+`%i1*@WQx9cmbQfOt zmML)D)02N#vps<6yk;QZBu(|gjwKb0wkMXjX(l^w;xTzLp;Jo2{OX*IYn~}vCC)MZ zY;4?bx^>?Btu?$S1f{IkEZ^Md8N4y~*~VqpKJT4&m+^Pvr1uWmN9`W}SP6EsWuf8aw5$ z9;lqMUnFhP+M|zWHROJHP*D<{xKCck=E>LJQjc^^H?3dj6 mYkw<9U2`{oR{v+O^#``()n_eVyuWD%N)?{2elF{r5}E*@cn#11 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/Contents.json new file mode 100644 index 00000000..327672f9 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_handsup@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_handsup@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/chatsalon_handsup@1x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup.imageset/chatsalon_handsup@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..7ae39baf43263aaec548ea854296a6dc51472925 GIT binary patch literal 1412 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 UBJqR&;Q#;t07*qoM6N<$g7}lVTL1t6 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_list.imageset/chatsalon_handsup_list@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_list.imageset/chatsalon_handsup_list@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..36700497dfb89f6909ba00c38ef4165145102cf8 GIT binary patch literal 3234 zcmV;T3|;eyP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91V4wp41ONa40RR91U;qFB0I4%yP5=N53`s;mRCodHU3+j9)fxYGZ=OJ) z%0sGws(^u!KxY~tQ7l5OouVLuKy5^tLLbvVYAIG81*dhW1=|^AhS5$Hl`^(6)M>$# zT1uf+AP-_S1e%0I(GVUMC?)|+NbcQ!zrArjX~BvM)x zk{kKjC`+EkA(@$twp7`QU#;x-VZ@$S^MRK1`w|Xs0d%IyhLiOf9_W zuwCWbqJWylGsCWRc{efhG6vt4GVB5*oG&YZJ5cmWR<>tVQNfKD!qby|77kA3(bEqo z>)F9w%c&xSayk$0vQ|@8#^RC*pZ_RXS(8>k^|6*IUaz!=!5@~a zFzH0kO1R+hD6^+d9DO7ix#eVtE9=hO+vAh=_c!o?8S0F>1A}BRw5))t+LnhEUr#v? ztOg|`Kw8ss-GKqHuv!mGpCAYb1R(BR^`*RMZ2vCx&I%NepVE0KoTv;qQM%_IG> z!HtD^cp7>~+(n&Ywu@@25yl`Z(9iEzUCnTC%{;4rP#zPhn3*6jrGTEgQ_nEtelf^0 zfmz%vzzUef&Bz(zeu6N!!|SqtHp9%#qep<(qvyq&JBq0Q%xZRbc^muM#F`!^`<^g? zmznJuA8Qsh<|hbK$}afU6~x#L1%|OWM12DSizx@)!B#Bz;-_Jd#)~@Bqb=%WL}J09 zdn)T%v62;4L6PW^iJN)Xv}DL_qdo9WRZ_fxp_kNE!7s5g4C~AhKS33|hRcL$xr~?; zS~d{_OJEv_y+Hw-*@Ff2NSWO@>j(sl5)5`v1_i)$gq4sM)(h6*NIfMmRn2n3iqfK1@RDiX)qScIEQ9-n7*``1U{Pk2_zd0Rsoo^6z|~ZXMGHnNZCZ{iS>tz5m|7Y0{)G(wqk#j9K4vXU|ecyM8lEb5mnX8s{hS zU{}SQ%2fqmTTrTm-nrxV^!%31YH|DazD4crpHk_PvZ%$gY=$(i⪇Nz~kuUA?ma z=H-DlKuVbc_Wk{DI;{S&FCilW9W5TvIDgRGL|3m|F{C*;g2%iwA)k!hh>x9LAGy2LmSXV09WM@tvc^0G&0;r#pQNOff#3g;wa6C$veu@y9Yc zL0hzRr^f^P4F3*vr;D1ne0KF-5|<=81+d2(Fe-W$H^oi_;Ceyk*|`2|UT!D4CU`UU zc`}dn0}d}tP`FvdBEZnVEaw=Yl^FPhAqH=l}2*bPvO(A|BFDh?lvn4|tb$0Np{KmT9CFYNttOQ|o+3?hQYN)SQ`2pB9>wZS}ehtPJZZIIg*z-V)@CFDACr_T#@%q)qUr^oA z_jPgZgC7B4&jT@~RU{ze#@?o5hxz*TYgYwlEp>_g`~lc!z`Gz({1qm%Sj~TE5gj{r zRF}Q2?Nj>cnw7NWg{``HJ0H?vE(qA;4G_A(I`b=Er9xio4G$+j{E#+0^&}}iaqUfb z8R_;6>}B}X6fO9Ql~0hzV=x4!ibLlj+FaIr|1 zeU29}2lg^N%5pEXR&))^zWqHKG2#Z%Z2Js9U=Hk6s|Z%c0ns(f$<3i3u2?CWZJ*(% zVXi6w?tJa2*`3p85PohjBA{WeDgeHec}~c%fy_vjcnscx+}zy63HvmKh0JQ-`vdARxppeEc8+HO~k7A*V*jk_&vjW2}55{h+D0q`Qu zo+FGV$^wd)Wto2b_!^$~<5f@_LsnL{jobyXW{g#=1MGqdz>W=uXSbkY3~a_vm_QFM zSY(J788PAp=XZO7v9>z~bq^{44{+g*t6gCkZ#x<`e7Ifgsi4#!xh0Qk@6 zf+DYi2#{dFfC2Q_ik}GJWMq+*olT3s`KU3$Suw{07zd@&DL|c)VE_5SR2y!l-!+3~ z+&xP;=hD)pG;-uf;e3TMWNgEyeGIK4+grj>M+0BS3N1W@nYX8hHb3`kdUMyGLSn7o z-aYFcTDSh^`7x<1K>%AphaIQ_IMwsJr;=tk2%J_R#Ox#Qb!t zwKbv9U$~hTKl}*IzHg45Vv6A{OUv&l9A#J#iKu|UTktMlQ{pk@(xpq(&Wko?1OJQY zbJtx*g9i^WOVX?PSl(Lx_eXSB6Hx(>)^*q%Q0-2224 z0EW@LWr15%1t1Z}cCZF7;@%C3BLM7xVJym+3V^pi9NQ6#ftwZ`0bm!)VrlU!Z|bXbDC6udSDHonZk^P zALC?3$aKo1V#HXPJ>{4IF2t@SO7HbOI!$vNATn$gJmd$Yxpr$PB;uY|FBM z2MQ z==0`8l=+!wm4Y8|*PIEuu~+)gZPBBcp`140XNk2DWOBl5ki z3P6!q-o)VrJZxKS=R$wv>RF5Be|;D zU%y9L)sgHZye*-5tlkIy)x3FG*^iwm*c_qR=Ue3|icUxcMF|ti2To1lR}-!s;a$-0 zTu{nqf%CW>$>VP|d-~FR9jX2fsRek>ONfF3X0u`*bo=W-zoS12aeQK Uxn_jQQvd(}07*qoM6N<$f(dXGEdT%j literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/Contents.json new file mode 100644 index 00000000..14562a92 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_handsup_success.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_handsup_success@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/chatsalon_handsup_success.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_handsup_success.imageset/chatsalon_handsup_success.png new file mode 100644 index 0000000000000000000000000000000000000000..14c4ebf03a55bb6a24f94c0d20681532f3f88e40 GIT binary patch literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz1&TfmH9gB0%lVEGG3-STvC4ABss z+P9yN(NUoN{QM`67+o?{r1nOgWcDbL;$QfI<<{jDs&P)0z2}4{c&KQ#I+ZwGGrwv3 z?Z)0Yp8L+6$$xHc?f8Im=@kyYfM&ZZwu__E5*Tb}G#`mj-@2jKb+_TyNivaD8LuX= zI?wQWZ#3-!Yq*a<`lkm*yLdX)KC@>2Ggad*dG?MkWU2D~2VB+@ZoFE;_oVwuzWGAgdgTt@*MmS4;VtuW>;ryRtRX(|{?+;zB`aVr_v5Ak{y_e??-%UMJT=XZ| mWdF9veU0xo%e&>Dyu+=Y`t>S4(?lMwtsYg&HrMA)g>tF*l%J?&q71TDD_n zRQDx%@40$J%E;M;>vYQ_hg9O4d~d#op%zTY5hFhA!f>rI12Z&ya# QHU!0~r>mdKI;Vst0QN`dcmMzZ literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/Contents.json new file mode 100644 index 00000000..aff1264f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_leave_mic@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_leave_mic@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@1x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..82a96b38acbe871c46e0cc0f37ba72ee6ff6cccd GIT binary patch literal 1903 zcmV-#2ax!QP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NI*-1n}RA>d&T5C*HM-=|%@)X2^ zQk9p80VTH5myKYXR9Z2%u@!5qHEOUH@zKO*@qwaJK`K?#HX#ukFj`~fC7LuUT5DTd z!TMx!<>arrN6>b(2Mi zlbMJK{OP7f7Xxb$8IJMiA$RmW6c*-LrAA)QtJ;8b6%}sH4|K~#u$2(?J*-#P!6#$2 z3}Tv-x8wHFzP=4=wAgHb$jAN6Hk(Ylelf{&U;Z02RSBS6?VW|Uth^aM9N3hI7Xr>$ zVj;R|+g6*dSthLkY_E=% zZoU#q7>#&M44`$M_k8y(l|~?Je&yICj79`_|uBzGM-qtE;6J>+9;Ua>Wu{ zzjjp-L3x=LadT(mKwdWPR8*jj8=%o##J03lq-@%NmKGZ}U+zj0*0vTT11K<)VjIO~ zEfc@}dMhqoIFDtE7owuP9Puj_1rHYY276IQ}Z zm68DzRdysWTc5NULxYBaMq+Nv45{aRe0`Ce`jxEVD_1o5=k_fb-I!32pJV)K`JD%m z5@yaJ89*ViWp2wgo}QjaN!RF_xPS*@Se}ANBWMbWhO^PE#jFIEVo5)%FAk2i_ zVcw#p3q&B?8ndN3|9~O5dGk8bwta)Zz@ZoyIUXgK&LejIXYlp)Gl=ckorRq{(h(RG zgz)gO_#pa2xVpOF#`SAxZf=(Nfu0+QkuH85J<5tS+Q0brOo#9; zDSLKhVprBq6WvZu&X_iR24>ERft$O#Nu8PxerhYFRY+P-)d4pn&VFUz zk6W-1fkT7LMLPUV*ab?os@0$=xrB%}-c;<#0v_wv)chw?`RZ$sslJR$jK$r=;v=2~>R)Nh!_X_tojk5CAQaIbnA_vXRrO$ pz}N_S@3lXBm>WXh&+>Ph{{ghW$o9WkXVL%w002ovPDHLkV1kb)cZL7} literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_leave_mic.imageset/chatsalon_leave_mic@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3b709e10cf20b8cc5ba1fd8b47786968bcaa3210 GIT binary patch literal 4169 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/Contents.json new file mode 100644 index 00000000..fad50d0e --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_loading@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_loading@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/chatsalon_loading@1x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_loading.imageset/chatsalon_loading@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..07dd7274cf1c260d10ffebb967e82031b30ba7f1 GIT binary patch literal 1090 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/Contents.json b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/Contents.json new file mode 100644 index 00000000..c81c8978 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "filename" : "chatsalon_master@1x.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "chatsalon_master@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@1x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..50542ad96a4d572be10cb945cf06435977e965bc GIT binary patch literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1|;P@bT0xa#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz1&TfmH9gB0%lVEGHEEZ5V;F+@YO zH^|WMu!F#y&1)q%1A`=9c!)1`DN$ft)M9^xrNTiT8 zOG*@2+~)M(Eq(WhfmM61?Yy~>_utNQGL2enxuTzML0QMT{$R}ny~H%X31{|4?M!F< zwuyJe9{vi!n&OTPVkeW%$UKiQ7WFye-+aHbOY5B3YAM#6a-qsCpOEVlk}ly!?0Z$|fNjziUkuO6|kvQXNiaQ~CR?~oLR-c178U(;(Zg^Hom)bvgTe~DWM4f>b|^i literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_master.imageset/chatsalon_master@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..135f3ba6d9c0bc3726682729c1b2df5d84fa7c38 GIT binary patch literal 1068 zcmV+{1k?M8P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR919H0XL1ONa40RR918~^|S0A#)Nq5uE`mPtfGR7efIR!wLVK@@(oN!5!7 zDS}N>L8KHx1o5CEB8bI>( z7SUrO-lz;`zXso(59PGbP$-=hEq6uh&K3Paqf!&1q*sc$7vZPmv$0^|*ACH3Pa$-` z1SnNP`?aLxEk^l6S~hTGB8z`9QoU1rIU!1&f=@2+9~YHAFU4&?&3o)`x!|RlBjWon zLDY)gf;e?sj<-FMbIOm!EpI;4DS0<@QN+K4SwTnCtfW$BWT@>!+__$mV%4Sh2xvi% z--zCLK}NRD#RHnQdwy>gweT3DJ&6u4ikI$+i+T|Or;#J0n0ODQJ$ri1VkBb+8SBYI z!$nSV2dD{h&CE1nWZN@0rC(J;r)5vh1b;3tHkZ3$W{I4J+d5l8lZ{9at{JCsB{9bN zexLcd1o@pD9?^)z4uQ=_$=(y(VFp6y@EQV&-$?L~dWMQj2TIvk|}v z630;67kryX?{L~6)0%?WNMFR5*myw1ou!~Xh{NM5^ixWsmzVK67=BvCbI`;vHjWy1 zhJtP|aHRbj7Jb0&6jQ12qL>2XVbMdK=E&g6LHAo@~%Y9~aCaZ;Ue(L_H&L z>buadHz9F?wQk@<8-1LJxXTb^@dQ|6T$rxxf?vvIHa6qq@QAqe7z9zN3Dz@~n1;~1 zqt8k{!S|T`p&cRS6MaL2oa8p}M$_h6kS|Rjr8{jslVaT8wn3)k8#ZgN3}yiO9E}b^)<_m+-Ue_5;TmFexE2_oc(R@)q2!6Q=k_GTtQR{#8-0>6T;L=EjamWD zmp+<}%ficg)~sSA$&>H>*a6e!SKve;R^!OxgLJVYWQ%tYUJK|jRT)6m)oiq{1&l3~ z?ins}8g5Ha8zJA<^@>43UU+y12}i2tzauFM?(Ahy0A?e78N*p3N8&z1&-xLD!RvZW m3`O}|w~KIGlPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR917@z|H1ONa40RR917ytkO0OB=utpET5n@L1LR7efAR^3ZeVH|$Wnr_Ov zuncM0=OUKaU1T3OMP3vGh3+bduA;COh(uHu{s{>gq!$%|5QyZ3P=qZa3&RYf%%Z`n zd7R)fr}J!{oxS~jwzDtJj#Kl2XYYC6-}^q#`~6OW34{>U6mBGXh%Ta&$dHMCVjrb!*VWCj)#tWeLlX*c&sQU^ z`>;mtNT`74d?nMOi{_`Sm01(Y@FJPwM$e3>yef;WEfeDY>!@knRIrn$N}>#J#Q<>~ z(GXpO3eI+f(=m%h!bocsYPVRSs6bgsI+XpPQD%pQet4f36z3MNzQs97BbgK!_#Q{Q zFA7iFRJuIxgEbqi^uve96!C<}iSOT8ipfY4G*$3j+msW_%Xrv;PiWCNu&Wd&_u27a zAc~hHzI~(V;9WdLnbpp-=^0iq5~N8^;h@Wg6Sa0cdNYq_&6OAnCGgh2pofi8CmR&R zlMgYx52&!0NI10HhWZ*Cx(4TQ`M87DWdVI36%0|_3~ay`mm&64S@Bs`asEg-j=61k z{7%88qYhl}o9Nj|-y!8&;c`=83=PDro z(H41_MrHy(=o~beotoC(h;ZKwiKm}pVltwMpT860_VZb>xmgzdUt(rWIo8Am)kMQ< znZ@_s3W={FRh()Mi?WMBQE_EloaqRQQCVdHGq5HfVz7zfRdLrhx7cf4<-)^h!DU6_ z-&K(^;H^4FT+jJ@{F>IVtz{xzyuo2XxUJys=6bV4H@$S34Me?KyX#u-8kwx!gOg># vBU#DYu=JCeW%A!1eMuKJN@*mk{@d~wdx}F#LdLge00000NkvXXu0mjf0G4Ji literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_mute.imageset/chatsalon_mic_mute@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_mute.imageset/chatsalon_mic_mute@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5d91b880106c148180d3558a009d9c3fef0c1638 GIT binary patch literal 1720 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 literal 0 HcmV?d00001 diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_off.imageset/chatsalon_mic_off@2x.png b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonAssets.xcassets/chatsalon_mic_off.imageset/chatsalon_mic_off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9ebee9fae59d61d17df392892364ae86c28623dc GIT binary patch literal 4061 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 TRTCChatSalon { + if let room = chatSalon { + return room + } + chatSalon = TRTCChatSalon.shared() + return chatSalon! + } + /* + 在无需使用VoicRoom的场景,可以将单例对象销毁。 + 例如:退出登录时。 + 在本Demo中没有调用到改销毁方法。 + */ + /// 销毁chatSalon单例 + func clearChatSalon() { + TRTCChatSalon.destroyShared() + chatSalon = nil + } + + + /// 语聊房入口控制器 + /// - Returns: 返回语聊房的主入口 + @objc func makeEntranceViewController() -> UIViewController { + return makeChatSalonListViewController() + } + + + /// 创建语聊房页面 + /// - Returns: 创建语聊房VC + func makeCreateChatSalonViewController() -> UIViewController { + return TRTCCreateChatSalonViewController.init(dependencyContainer: self) + } + + + /// 房间列表页面 + /// - Returns: 语聊房列表VC + func makeChatSalonListViewController() -> UIViewController { + return TRTCChatSalonListViewController.init(dependencyContainer: self) + } + + /// 语聊房 + /// - Parameters: + /// - roomInfo: 要进入或者创建的房间参数 + /// - role: 角色:观众 主播 + /// - Returns: 返回语聊房控制器 + func makeChatSalonViewController(roomInfo: ChatSalonInfo, role: ChatSalonViewType, toneQuality:ChatSalonToneQuality = .music) -> UIViewController { + return TRTCChatSalonViewController.init(viewModelFactory: self, roomInfo: roomInfo, role: role, toneQuality: toneQuality) + } +} + +extension TRTCChatSalonEnteryControl: TRTCChatSalonViewModelFactory { + + /// 创建语聊房视图逻辑层(MVC中的C,MVVM中的ViewModel) + /// - Returns: 创建语聊房页面的ViewModel + func makeCreateChatSalonViewModel() -> TRTCCreateChatSalonViewModel { + return TRTCCreateChatSalonViewModel.init(container: self) + } + + /// 语聊房视图逻辑层(MVC中的C,MVVM中的ViewModel) + /// - Parameters: + /// - roomInfo: 语聊房信息 + /// - roomType: 角色 + /// - Returns: 语聊房页面的ViewModel + func makeChatSalonViewModel(roomInfo: ChatSalonInfo, roomType: ChatSalonViewType) -> TRTCChatSalonViewModel { + return TRTCChatSalonViewModel.init(container: self, roomInfo: roomInfo, roomType: roomType) + } + + /// 语聊房列表视图逻辑层(MVC中的C,MVVM中的ViewModel) + /// - Returns: 语聊房列表的Viewmodel + func makeChatSalonListViewModel() -> TRTCChatSalonListViewModel { + return TRTCChatSalonListViewModel.init(container: self) + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/SubViews/TRTCChatSalonListCell.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/SubViews/TRTCChatSalonListCell.swift new file mode 100644 index 00000000..92746a37 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/SubViews/TRTCChatSalonListCell.swift @@ -0,0 +1,103 @@ +// +// TRTCChatSalonListCell.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/12. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCChatSalonListCell: UICollectionViewCell { + private var isViewReady: Bool = false + + let coverImageView: UIImageView = { + let imageView = UIImageView.init(frame: .zero) + imageView.contentMode = .scaleAspectFill + return imageView + }() + + let anchorNameLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = "" + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .left + return label + }() + + let roomNameLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = "" + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .left + label.numberOfLines = 0 + return label + }() + + let memberCountLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = "" + label.font = UIFont.systemFont(ofSize: 12.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .left + label.adjustsFontSizeToFitWidth = true + return label + }() + + func setCell(model: ChatSalonInfo) { + let imageURL = URL.init(string: model.coverUrl) + let imageName = "voiceroom_cover1" + self.coverImageView.sd_setImage(with:imageURL, placeholderImage:UIImage.init(named: imageName) ,completed: nil) + self.anchorNameLabel.text = model.ownerName + self.roomNameLabel.text = model.roomName + self.memberCountLabel.text = "\(model.memberCount)\(String.online)" + } + + // MARK: - 视图生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() + activateConstraints() + backgroundColor = UIColor.init(0x000000, alpha: 0.5) + } + + func constructViewHierarchy() { + addSubview(coverImageView) + addSubview(anchorNameLabel) + addSubview(roomNameLabel) + addSubview(memberCountLabel) + } + + func activateConstraints() { + coverImageView.snp.makeConstraints { (make) in + make.top.leading.trailing.bottom.equalToSuperview() + } + roomNameLabel.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(6.0) + make.bottom.equalToSuperview().offset(-6.0) + make.width.lessThanOrEqualToSuperview().multipliedBy(0.55) + } + anchorNameLabel.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(6.0) + make.bottom.equalTo(roomNameLabel.snp.top).offset(-6.0) + make.width.lessThanOrEqualToSuperview().multipliedBy(0.6) + } + memberCountLabel.snp.makeConstraints { (make) in + make.right.equalToSuperview().offset(-6.0) + make.bottom.equalToSuperview().offset(-6.0) + make.width.lessThanOrEqualToSuperview().multipliedBy(0.38) + } + } + + +} + +fileprivate extension String { + static let online = ChatSalonLocalized.getLocalizedString(key: "online") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListRootView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListRootView.swift new file mode 100644 index 00000000..c011c17a --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListRootView.swift @@ -0,0 +1,202 @@ +// +// TRTCChatSalonListRootView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/12. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit +import SnapKit +import Toast_Swift +import NVActivityIndicatorView + +class TRTCChatSalonListRootView: UIView { + private var isViewReady: Bool = false + let viewModel: TRTCChatSalonListViewModel + weak var rootViewController: UIViewController? + var scrollviewBaseContentOffsetY:CGFloat = 0.0 + + init(frame: CGRect = .zero, viewModel: TRTCChatSalonListViewModel) { + self.viewModel = viewModel + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + let loading = NVActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 100, height: 60), + type: .ballRotate, + color: .searchBarBackColor) + + let backgroundLayer: CALayer = { + // fillCode + let layer = CAGradientLayer() + layer.colors = [UIColor.init(0x13294b).cgColor, UIColor.init(0x000000).cgColor] + layer.locations = [0.2, 1.0] + layer.startPoint = CGPoint(x: 0.4, y: 0) + layer.endPoint = CGPoint(x: 0.6, y: 1.0) + return layer + }() + + let createButton: UIButton = { + let button = UIButton.init(type: .custom) + button.setImage(UIImage.init(named: "voiceroom_create_room"), for: .normal) + return button + }() + + let roomListCollection: UICollectionView = { + let layout = UICollectionViewFlowLayout.init() + let itemWidth = (UIScreen.main.bounds.width - 40 - 5) / 2.0 + layout.itemSize = CGSize.init(width: itemWidth, height: itemWidth) + layout.minimumLineSpacing = 5.0 + layout.minimumInteritemSpacing = 5.0 + layout.scrollDirection = .vertical + layout.sectionInset = UIEdgeInsets.init(top: 0, left: 20, bottom: 40, right: 20) + let collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: layout) + collectionView.register(TRTCChatSalonListCell.self, forCellWithReuseIdentifier: "TRTCChatSalonListCell") + collectionView.backgroundColor = UIColor.clear + collectionView.bounces = true + return collectionView + }() + + // MARK: - 视图生命周期 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + bindInteraction() + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + backgroundLayer.frame = self.bounds; + layer.insertSublayer(backgroundLayer, at: 0) + addSubview(roomListCollection) + addSubview(createButton) + addSubview(loading) + } + + func activateConstraints() { + roomListCollection.snp.makeConstraints { (make) in + make.top.leading.trailing.bottom.equalToSuperview() + } + createButton.snp.makeConstraints { (make) in + make.height.width.equalTo(66) + make.right.equalToSuperview().offset(-20) + if #available(iOS 11.0, *) { + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-30) + } else { + // Fallback on earlier versions + make.bottom.equalToSuperview().offset(-30) + } + } + loading.snp.makeConstraints { (make) in + make.center.equalToSuperview() + make.height.width.equalTo(60) + } + } + + func bindInteraction() { + createButton.addTarget(self, action: #selector(createButtonAction(_:)), for: .touchUpInside) + roomListCollection.delegate = self + roomListCollection.dataSource = self + let header = MJRefreshStateHeader(refreshingTarget: self, refreshingAction: #selector(refreshListAction)) + header.setTitle(String.pullRefresh, for: .pulling) + header.setTitle(String.refreshing, for: .refreshing) + header.setTitle("", for: .idle) + header.lastUpdatedTimeLabel?.isHidden = true + roomListCollection.mj_header = header + } + + @objc + func createButtonAction(_ sender: UIButton) { + let viewController = viewModel.makeCreateViewController() + rootViewController?.navigationController?.pushViewController(viewController, animated: true) + } + + @objc + func refreshListAction() { + viewModel.getRoomList() + } +} + +extension TRTCChatSalonListRootView: UICollectionViewDelegate { + public func updateBaseCollectionOffsetY() -> Void { + scrollviewBaseContentOffsetY = roomListCollection.contentOffset.y + } + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + // 检查是否是自己的房间 + viewModel.clickRoomItem(index: indexPath.row) + collectionView.panGestureRecognizer.isEnabled = true + } + func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool { + return true + } + func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) { + if fabsf(Float(collectionView.contentOffset.y - scrollviewBaseContentOffsetY)) <= 0.001 && + !collectionView.isDragging && + !collectionView.isDecelerating { + //bugfix 7P下拉刷新后,collectionCell无法选中 + collectionView.panGestureRecognizer.isEnabled = false + DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1) { + collectionView.panGestureRecognizer.isEnabled = true + } + } + } +} + +extension TRTCChatSalonListRootView: UICollectionViewDataSource { + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return viewModel.roomList.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TRTCChatSalonListCell", for: indexPath) + if let roomCell = cell as? TRTCChatSalonListCell { + let roomInfo = viewModel.roomList[indexPath.row] + roomCell.setCell(model: roomInfo) + } + return cell + } +} + +extension TRTCChatSalonListRootView: TRTCChatSalonListViewResponder { + func pushRoomView(viewController: UIViewController) { + rootViewController?.navigationController?.pushViewController(viewController, animated: true) + } + + func showToast(message: String) { + self.makeToast(message) + } + + func refreshList() { + roomListCollection.reloadData() + } + + func stopListRefreshing() { + roomListCollection.mj_header?.endRefreshing() + } + + func showLoading(message: String) { + loading.startAnimating() + } + + func hideLoading() { + loading.stopAnimating() + } +} + +/// MARK: - internationalization string +fileprivate extension String { + static let pullRefresh = ChatSalonLocalized.getLocalizedString(key: "pull down to refresh") + static let refreshing = ChatSalonLocalized.getLocalizedString(key: "loading…") +} + + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewController.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewController.swift new file mode 100644 index 00000000..16ce147e --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewController.swift @@ -0,0 +1,79 @@ +// +// ChatSalonListViewController.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/12. +//Copyright © 2020 tencent. All rights reserved. +// +import UIKit + +/// 语聊房列表页 +public class TRTCChatSalonListViewController: UIViewController { + // 依赖管理者 + let dependencyContainer: TRTCChatSalonEnteryControl + var viewModel: TRTCChatSalonListViewModel? + + init(dependencyContainer: TRTCChatSalonEnteryControl) { + self.dependencyContainer = dependencyContainer + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + // MARK: - life cycle + public override func viewDidLoad() { + super.viewDidLoad() + title = .controllerTitle + let backItem = UIBarButtonItem.init(image: UIImage.init(named: "navigationbar_back"), style: .plain, target: self, action: #selector(cancel)) + self.navigationItem.leftBarButtonItem = backItem + let rightItem = UIBarButtonItem.init(image: UIImage.init(named: "help_small"), style: .plain, target: self, action: #selector(connectWeb)) + self.navigationItem.rightBarButtonItem = rightItem + } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: false) + } + + public override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + viewModel?.getRoomList() // 调整房间列表的刷新时机 + guard let rootView = self.view as? TRTCChatSalonListRootView else { + return + } + rootView.updateBaseCollectionOffsetY() + } + + + public override func loadView() { + // Reload view in this function + let viewModel = dependencyContainer.makeChatSalonListViewModel() + let rootView = TRTCChatSalonListRootView.init(viewModel: viewModel) + viewModel.viewResponder = rootView + self.viewModel = viewModel + rootView.rootViewController = self + view = rootView + } + + /// 取消 + @objc func cancel() { + navigationController?.popViewController(animated: true) + } + + /// 连接官方文档 + @objc func connectWeb() { + if let url = URL(string: "https://cloud.tencent.com/document/product/647/35428") { + UIApplication.shared.openURL(url) + } + } +} + +private extension String { + static let controllerTitle = ChatSalonLocalized.getLocalizedString(key: "chat salon") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewModel.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewModel.swift new file mode 100644 index 00000000..5fa8ecb5 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonListViewController/TRTCChatSalonListViewModel.swift @@ -0,0 +1,125 @@ +// +// TRTCChatSalonListViewModel.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/12. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +protocol TRTCChatSalonListViewResponder: class { + func showToast(message: String) + func refreshList() + func stopListRefreshing() + func showLoading(message: String) + func hideLoading() + func pushRoomView(viewController: UIViewController) +} + +class TRTCChatSalonListViewModel { + private let dependencyContainer: TRTCChatSalonEnteryControl + weak var viewResponder: TRTCChatSalonListViewResponder? + private var chatSalonManager: TRTCChatSalonManager { + return TRTCChatSalonManager.shared + } + + private var chatSalon: TRTCChatSalon { + return dependencyContainer.getChatSalon() + } + // 视图相关属性 + private(set) var roomList: [ChatSalonInfo] = [] + + /// 初始化方法 + /// - Parameter container: 依赖管理容器,负责ChatSalon模块的依赖管理 + init(container: TRTCChatSalonEnteryControl) { + self.dependencyContainer = container + } + + func makeCreateViewController() -> UIViewController { + return dependencyContainer.makeCreateChatSalonViewController() + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + @objc + func getRoomList() { + guard dependencyContainer.mSDKAppID != 0 else { + viewResponder?.showToast(message: String.toastAppIdError) + return + } + chatSalonManager.getRoomList(sdkAppID: dependencyContainer.mSDKAppID, success: { [weak self] (roomIds: [String]) in + guard let `self` = self else { return } + let roomIdsInt = roomIds.compactMap { + Int($0) + } + if roomIdsInt.count == 0 { + DispatchQueue.main.async { + self.roomList = [] + self.viewResponder?.refreshList() + self.viewResponder?.showToast(message: String.toastEmptyContent) + self.viewResponder?.stopListRefreshing() + } + return; + } + self.chatSalon.getRoomInfoList(roomIdList: roomIdsInt.map{ NSNumber.init(value: $0) }) { [weak self] (code, message, roomInfos: [ChatSalonInfo]) in + guard let self = self else { return } + self.viewResponder?.stopListRefreshing() + if code == 0 { + if roomInfos.count == 0 { + self.viewResponder?.showToast(message: String.toastEmptyContent) + } + DispatchQueue.main.async { + self.roomList = roomInfos + self.viewResponder?.refreshList() + } + } else { + TRTCLog.out("get room list failed. code\(code), message:\(message)") + self.viewResponder?.showToast(message: String.toastGetInfoListFailed) + } + DispatchQueue.main.async { + self.viewResponder?.stopListRefreshing() + } + } + }) { [weak self] (code, message) in + guard let `self` = self else { return } + TRTCLog.out("error: get room list fail. code: \(code), message:\(message)") + self.viewResponder?.showToast(message: String.toastGetListFailed) + self.viewResponder?.stopListRefreshing() + } + DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { + self.viewResponder?.stopListRefreshing() + } + } + + func clickRoomItem(index: Int) { + let roomInfo = self.roomList[index] + if dependencyContainer.userID == roomInfo.ownerId { + // 开始进入已经存在的房间 + startEnterExistRoom(info: roomInfo) + } else { + // 正常进房逻辑 + enterRoom(info: roomInfo) + } + } + + func startEnterExistRoom(info: ChatSalonInfo) { + // 以主播方式进房 + let vc = self.dependencyContainer.makeChatSalonViewController(roomInfo: info, role: .anchor) + self.viewResponder?.pushRoomView(viewController: vc) + } + + func enterRoom(info: ChatSalonInfo) { + let vc = self.dependencyContainer.makeChatSalonViewController(roomInfo: info, role: .audience) + self.viewResponder?.pushRoomView(viewController: vc) + } +} + +fileprivate extension String { + static let toastAppIdError = ChatSalonLocalized.getLocalizedString(key: "invalid appid") + static let toastEmptyContent = ChatSalonLocalized.getLocalizedString(key: "No content yet~") + static let toastGetInfoListFailed = ChatSalonLocalized.getLocalizedString(key: "Failed to get room list") + static let toastGetListFailed = ChatSalonLocalized.getLocalizedString(key: "Failed to get list") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonLocalized.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonLocalized.swift new file mode 100644 index 00000000..71cabc58 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonLocalized.swift @@ -0,0 +1,32 @@ +// +// TRTCChatSalonLocalized.swift +// TXLiteAVDemo +// +// Created by abyyxwang on 2021/3/3. +// Copyright © 2021 Tencent. All rights reserved. +// + +import Foundation + + +class ChatSalonLocalized { + static func getLocalizedString(key: String, comment: String = "") -> String { + return .localized(of: key, comment: comment) + } +} + +private let bundleID = Bundle.main.bundleIdentifier ?? "" +private let bundle = Bundle.init(identifier: bundleID) +private let tableName = "TRTCChatSalonDemoLocalized" + +private extension String { + static func localized(of key: String, comment: String = "") -> String { + guard let bundle = bundle else { + return key + } + return NSLocalizedString(key, + tableName: tableName, + bundle: bundle, + comment: comment) + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceListView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceListView.swift new file mode 100644 index 00000000..6de490d3 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceListView.swift @@ -0,0 +1,154 @@ +// +// TRTCCSAudienceListView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/14. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCCSAudienceListView: UIView { + private var isViewReady: Bool = false + let viewModel: TRTCChatSalonViewModel + + init(frame: CGRect = .zero, viewModel: TRTCChatSalonViewModel) { + self.viewModel = viewModel + super.init(frame: frame) + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + let container: UIView = { + let view = UIView.init(frame: .zero) + view.backgroundColor = .pannelBackColor + return view + }() + + let titleContainer: UIView = { + let view = UIView.init(frame: .zero) + return view + }() + + let titleLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = String.listTitle + label.font = UIFont.systemFont(ofSize: 16.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .center + return label + }() + + let closeButton: UIButton = { + let button = UIButton.init(type: .custom) + button.setTitle(String.close, for: .normal) + return button + }() + + let tableView: UITableView = { + let tableView = UITableView.init(frame: .zero) + tableView.register(TRTCCSAudienceTableViewCell.self, forCellReuseIdentifier: "TRTCCSAudienceTableViewCell") + tableView.backgroundColor = UIColor.clear + tableView.rowHeight = 64 + tableView.separatorStyle = .none + return tableView + }() + + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + deinit { + + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(container) + container.addSubview(titleContainer) + titleContainer.addSubview(titleLabel) + titleContainer.addSubview(closeButton) + container.addSubview(tableView) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + container.snp.makeConstraints { (make) in + make.bottom.left.right.equalToSuperview() + make.height.equalTo(418) + } + titleContainer.snp.makeConstraints { (make) in + make.top.left.right.equalToSuperview() + make.height.equalTo(56) + } + titleLabel.snp.makeConstraints { (make) in + make.center.equalToSuperview() + } + closeButton.snp.makeConstraints { (make) in + make.centerY.equalTo(titleLabel.snp.centerY) + make.right.equalToSuperview().offset(-20) + } + tableView.snp.makeConstraints { (make) in + make.bottom.right.left.equalToSuperview() + make.top.equalTo(titleContainer.snp.bottom) + } + } + + func bindInteraction() { + /// 此方法负责做viewModel和视图的绑定操作 + closeButton.addTarget(self, action: #selector(hide), for: .touchUpInside) + tableView.delegate = self + tableView.dataSource = self + } + + func show() { + isHidden = false + } + + @objc + func hide() { + isHidden = true + } + + func refreshList() { + tableView.reloadData() + } +} + +extension TRTCCSAudienceListView: UITableViewDelegate { + +} + +extension TRTCCSAudienceListView: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return viewModel.requestTakeSeatMap.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "TRTCCSAudienceTableViewCell", for: indexPath) + let index = viewModel.requestTakeSeatMap.index(viewModel.requestTakeSeatMap.startIndex, offsetBy: indexPath.row) + if let audienceCell = cell as? TRTCCSAudienceTableViewCell { + let (_, model) = viewModel.requestTakeSeatMap[index] + audienceCell.setCell(model: model) + } + return cell + } +} + +/// MARK: - internationalization string +fileprivate extension String { + static let listTitle = ChatSalonLocalized.getLocalizedString(key: "Raised hands") + static let close = ChatSalonLocalized.getLocalizedString(key: "Close") +} + + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceTableViewCell.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceTableViewCell.swift new file mode 100644 index 00000000..defe0e7d --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCCSAudienceTableViewCell.swift @@ -0,0 +1,121 @@ +// +// TRTCCSAudienceTableViewCell.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/15. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCCSAudienceTableViewCell: UITableViewCell { + private var isViewReady: Bool = false + private var model: CSMemberRequestEntity? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + backgroundColor = UIColor.clear + selectionStyle = .none + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + let iconView: UIImageView = { + let view = UIImageView.init(frame: .zero) + view.contentMode = .scaleAspectFit + view.layer.cornerRadius = 22.0 + view.layer.masksToBounds = true + return view + }() + + let nameLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = "" + label.font = UIFont.systemFont(ofSize: 16.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .left + return label + }() + + let inviateButton: UIButton = { + let button = UIButton.init(type: .custom) + button.setBackgroundImage(UIImage(named: "chatsalon_add_mic"), for: .normal) + button.setBackgroundImage(UIImage(named: "chatsalon_added_mic"), for: .selected) + return button + }() + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + // MARK: - 视图的生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + contentView.removeFromSuperview() + constructViewHierarchy() + activateConstraints() + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(iconView) + addSubview(nameLabel) + addSubview(inviateButton) + } + + override func prepareForReuse() { + super.prepareForReuse() + model = nil + iconView.image = UIImage.init(named: "voiceroom_placeholder_avatar") + } + + func activateConstraints() { + iconView.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(20) + make.height.width.equalTo(44) + } + nameLabel.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.left.equalTo(iconView.snp.right).offset(15) + } + inviateButton.snp.makeConstraints { (make) in + make.width.equalTo(60) + make.height.equalTo(30) + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-20) + } + } + + func bindInteraction() { + inviateButton.addTarget(self, action: #selector(buttonAction(sender:)), for: .touchUpInside) + } + + @objc + func buttonAction(sender: UIButton) { + model?.action(sender.isSelected ? 1 : 0) + sender.isSelected = true + } + + func setCell(model: CSMemberRequestEntity) { + let avatarUrl = URL.init(string: model.userInfo.userAvatar) + iconView.sd_setImage(with: avatarUrl, placeholderImage:UIImage.init(named: "voiceroom_placeholder_avatar") ,completed: nil) + nameLabel.text = model.userInfo.userName + inviateButton.isSelected = model.type == CSAudienceInfoModel.TYPE_WAIT_AGREE + self.model = model + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonHandsUpTipsView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonHandsUpTipsView.swift new file mode 100644 index 00000000..dbe6dcac --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonHandsUpTipsView.swift @@ -0,0 +1,71 @@ +// +// TRTCChatSalonHandsUpTipsView.swift +// TXLiteAVDemo +// +// Created by jiruizhang on 2021/3/1. +// Copyright © 2021 Tencent. All rights reserved. +// + +import Foundation + +class TRTCChatSalonHandsUpTipsView: UIView { + static let kHeight: CGFloat = 40 + + private var isViewReady: Bool = false + + let handsImgView: UIImageView = { + let imgView = UIImageView(image: UIImage(named: "chatsalon_handsup_success")) + imgView.contentMode = .scaleAspectFit + + return imgView + }() + + let contentLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.textColor = UIColor.init(0xEBF4FF) + label.fontSize = 14 + label.text = String.successMsg + return label + }() + + // MARK: - 视图生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(handsImgView) + addSubview(contentLabel) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + + handsImgView.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(20) + make.height.width.equalTo(14) + make.centerY.equalToSuperview() + } + + contentLabel.snp.makeConstraints { (make) in + make.left.equalTo(handsImgView.snp_right).offset(8) + make.centerY.equalTo(handsImgView) + } + + } +} + +fileprivate extension UIColor { + static let backgroundBlue = UIColor.init(0x0062E3) +} + +fileprivate extension String { + static let successMsg = ChatSalonLocalized.getLocalizedString(key: "You raised your hand! We'll let the speakers know you want to talk~") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonMainMenuView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonMainMenuView.swift new file mode 100644 index 00000000..5221d7db --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonMainMenuView.swift @@ -0,0 +1,150 @@ +// +// TRTCChatSalonRootView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +//Copyright © 2020 tencent. All rights reserved. +// +import UIKit + +public typealias CSIconTuple = (normal: UIImage, selected: UIImage) + +protocol TRTCChatSalonMainMenuDelegate: class { + func menuView(menu: TRTCChatSalonMainMenuView, click item: UIButton, index: Int) +} + +class TRTCChatSalonMainMenuView: UIView { + private var isViewReady: Bool = false + private let icons: [CSIconTuple] + private var buttons: [UIButton] = [] + weak var delegate: TRTCChatSalonMainMenuDelegate? + /// 初始化方法 + /// - Parameters: + /// - frame: 视图frame + /// - icons: 视图菜单icons(最多5个,最少1个) + init(frame: CGRect = .zero, icons: [CSIconTuple] ) { + self.icons = icons + super.init(frame: frame) + buttons = createButtons(icons: icons) + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + lazy var menuStack: UIStackView = { + let stack = UIStackView.init(frame: .zero) + stack.axis = .horizontal // 布局方向 + stack.distribution = .equalSpacing // 主方向上的排布方式 + stack.alignment = .center // 子方向的对齐方式 + if self.icons.count > 1 { + let totalWidth = UIScreen.main.bounds.width - 44.0 - 30.0 * CGFloat(self.icons.count) + let spaceNumber = CGFloat(self.icons.count - 1) + stack.spacing = totalWidth / spaceNumber + } + return stack + }() + + + // MARK: - 视图的生命周期 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(menuStack) + buttons.forEach { (button) in + menuStack.addArrangedSubview(button) + } + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + menuStack.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(22) + make.right.equalToSuperview().offset(-22) + make.height.equalTo(30) + make.centerY.equalToSuperview() + } + buttons.forEach { (button) in + button.snp.makeConstraints { (make) in + make.height.width.equalTo(30) + } + } + } + + func bindInteraction() { + /// 此方法负责做viewModel和视图的绑定操作 + buttons.enumerated().forEach { (element) in + let index = element.offset + let button = element.element + button.addTarget(self, action: #selector(selectAction(_:)), for: .touchUpInside) + button.tag = 100 + index + } + } + + @objc + func selectAction(_ sender: UIButton) { + self.delegate?.menuView(menu: self, click: sender, index: sender.tag - 100) + } + + public func anchorType() { + let disableIndex = Set.init([1, 3]) + buttons.enumerated().forEach { (item) in + let offset = item.offset + let button = item.element + if disableIndex.contains(offset) { + button.isSelected = true; + } + } + } + + public func audienceType() { + let disableIndex = Set.init([1, 3]) + buttons.enumerated().forEach { (item) in + let offset = item.offset + let button = item.element + if disableIndex.contains(offset) { + button.isSelected = false; + } + } + } + + public func changeMixStatus(isMute: Bool) { + if buttons.count > 2 { + buttons[1].isSelected = !isMute + } + } +} + +extension TRTCChatSalonMainMenuView { + private func createButtons(icons: [CSIconTuple]) -> [UIButton] { + return icons.map { (infoTuple) -> UIButton in + let button = UIButton.init(type: .custom) + button.setImage(infoTuple.normal, for: .normal) + button.setImage(infoTuple.selected, for: .selected) + button.isSelected = true + return button + } + } +} + +/// MARK: - internationalization string +fileprivate extension String { + +} + + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatCell.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatCell.swift new file mode 100644 index 00000000..f3880693 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatCell.swift @@ -0,0 +1,49 @@ +// +// TRTCChatSalonSeatCell.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCChatSalonSeatCell: UICollectionViewCell { + private var isViewReady: Bool = false + + let seatView: TRTCChatSalonSeatView = { + let view = TRTCChatSalonSeatView.init(state: .cellSeatEmpty) + return view + }() + + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() + activateConstraints() + } + + func constructViewHierarchy() { + addSubview(seatView) + } + + func activateConstraints() { + seatView.snp.makeConstraints { (make) in + make.top.left.bottom.right.equalToSuperview() + } + } + + func setCell(model: ChatSalonSeatInfoModel) { + seatView.setSeatInfo(model: model) + } + + func setCell(audience: CSAudienceInfoModel) { + let seatInfo = ChatSalonSeatInfoModel.init(seatIndex: 0, isClosed: false, isUsed: true, isOwner: false, seatInfo: nil, seatUser: audience.userInfo) { (model) in + + } + seatView.setSeatInfo(model: seatInfo, showMute: false) + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatView.swift new file mode 100644 index 00000000..763940a3 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonSeatView.swift @@ -0,0 +1,222 @@ +// +// TRTCChatSalonRootView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +//Copyright © 2020 tencent. All rights reserved. +// +import UIKit + +// 设置字号和透明度的 +enum TRTCChatSalonSeatState { + case cellSeatEmpty + case cellSeatFull + case masterSeatEmpty + case masterSeatFull +} + +// 需要设置合理的高度和宽度获得正常的显示效果(高度越高,name和avatar之间的间距越大) +class TRTCChatSalonSeatView: UIView { + private var isViewReady: Bool = false + private var isGetBounds: Bool = false + private var state: TRTCChatSalonSeatState { + didSet { + stateChange() + } + } + + init(frame: CGRect = .zero, state: TRTCChatSalonSeatState) { + self.state = state + super.init(frame: frame) + bindInteraction() + stateChange() + setupStyle() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + override func draw(_ rect: CGRect) { + super.draw(rect) + guard !isGetBounds else { + return + } + let width = self.frame.width + avatarImageView.layer.cornerRadius = 25 + avatarImageView.layer.masksToBounds = true + speakView.layer.cornerRadius = 25 + speakView.layer.borderWidth = 4 + speakView.layer.borderColor = UIColor.init(0x0FA968).cgColor + } + + let avatarImageView: UIImageView = { + let imageView = UIImageView.init(frame: .zero) + imageView.contentMode = .scaleAspectFit + imageView.image = UIImage.init(named: "voiceroom_placeholder_avatar") + return imageView + }() + + let speakView: UIView = { + let view = UIView.init() + view.backgroundColor = UIColor.clear + view.isHidden = true + return view + }() + + let muteImageView: UIImageView = { + let imageView = UIImageView.init(frame: .zero) + imageView.contentMode = .scaleAspectFit + imageView.image = UIImage.init(named: "chatsalon_mic_mute") + imageView.isHidden = true + return imageView + }() + + let nameLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = "" + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = UIColor.init(0xFFFFFF) + label.textAlignment = .center + label.numberOfLines = 1 + label.adjustsFontSizeToFitWidth = true + return label + }() + + // MARK: - 视图生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func setupStyle() { + backgroundColor = .clear + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(avatarImageView) + addSubview(muteImageView) + addSubview(nameLabel) + avatarImageView.addSubview(speakView) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + avatarImageView.snp.makeConstraints { (make) in + make.top.left.right.equalToSuperview() + make.height.equalTo(snp.width) + } + muteImageView.snp.makeConstraints { (make) in + make.right.bottom.equalTo(avatarImageView) + make.height.width.equalTo(24) + } + + nameLabel.snp.makeConstraints { (make) in + make.left.right.equalToSuperview() + make.bottom.equalToSuperview() + } + + speakView.snp.makeConstraints { (make) in + make.left.right.top.bottom.equalToSuperview() + } + } + + func bindInteraction() { + /// 此方法负责做viewModel和视图的绑定操作 + } + + func setSeatInfo(model: ChatSalonSeatInfoModel, showMute: Bool = false) { + if model.isClosed { + // close 状态 + avatarImageView.image = UIImage.init(named: "voiceroom_seat_lock") + return + } + let isMute = model.seatInfo?.mute ?? false + if showMute { + muteImageView.isHidden = false + } else { + muteImageView.isHidden = !isMute + } + if model.isUsed { + // 有人 + if let userSeatInfo = model.seatUser { + avatarImageView.sd_setImage(with: URL.init(string: userSeatInfo.userAvatar), placeholderImage: UIImage.init(named: "voiceroom_placeholder_avatar"), options: .allowInvalidSSLCertificates, context: nil) + var masterIcon: UIImage? = nil + if model.isOwner { + masterIcon = UIImage(named: "chatsalon_master") + } + nameLabel.set(image:masterIcon, with: userSeatInfo.userName) + } + } else { + // 无人 + avatarImageView.image = UIImage.init(named: "voiceroom_placeholder_avatar") + } + + // 绿色边框 + if (model.isTalking) { + speakView.isHidden = false + } else { + speakView.isHidden = true + } + } +} + +extension TRTCChatSalonSeatView { + + private func stateChange() { + switch state { + case .cellSeatEmpty: + toEmptyStates(isMaster: false) + case .masterSeatEmpty: + toEmptyStates(isMaster: true) + case .cellSeatFull: + toFullStates(isMaster: false) + case .masterSeatFull: + toFullStates(isMaster: true) + } + } + + private func toEmptyStates(isMaster: Bool) { + let fontSize: CGFloat = 14.0 + nameLabel.font = UIFont.systemFont(ofSize: fontSize) + nameLabel.textColor = UIColor.init(0xFFFFFF) + } + + private func toFullStates(isMaster: Bool) { + let fontSize: CGFloat = 14.0 + nameLabel.font = UIFont.systemFont(ofSize: fontSize) + nameLabel.textColor = UIColor.init(0xFFFFFF) + } +} + +/// MARK: - internationalization string +fileprivate extension String { + +} + +fileprivate extension UILabel { + func set(image: UIImage?, with text: String) { + let mutableAttributedString = NSMutableAttributedString() + if let image = image { + let attachment = NSTextAttachment() + attachment.image = image + attachment.bounds = CGRect(x: 0, y: -3, width: 14, height: 14) + let attachmentStr = NSAttributedString(attachment: attachment) + + mutableAttributedString.append(attachmentStr) + mutableAttributedString.append(NSAttributedString(string: " ")) + } + + let textString = NSAttributedString(string: text) + mutableAttributedString.append(textString) + + self.attributedText = mutableAttributedString + } +} + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTakeSeatTipsView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTakeSeatTipsView.swift new file mode 100644 index 00000000..d41b949f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTakeSeatTipsView.swift @@ -0,0 +1,126 @@ +// +// TRTCChatSalonTakeSeatTipsView.swift +// TXLiteAVDemo +// +// Created by abyyxwang on 2021/3/1. +// Copyright © 2021 Tencent. All rights reserved. +// + +import UIKit + +class TRTCChatSalonTakeSeatTipsView: UIView { + static let kHeight: CGFloat = 92 + + private var isViewReady: Bool = false + let viewModel: TRTCChatSalonViewModel + var currentTakeSeatInfo: CSMemberRequestEntity? { + didSet { + contentLabel.text = "\(currentTakeSeatInfo?.userInfo.userName ?? (currentTakeSeatInfo?.userID ?? ""))\(String.takeSeatSuffix)" + } + } + + init(frame: CGRect = .zero, viewModel: TRTCChatSalonViewModel) { + self.viewModel = viewModel + super.init(frame: frame) + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + let contentLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.textColor = UIColor.init(0xEBF4FF) + label.fontSize = 14 + return label + }() + + let welcomeButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setTitle(.welcomeText, for: .normal) + button.setBackgroundImage(UIColor.init(0x0FA968).trans2Image(), for: .normal) + button.layer.cornerRadius = 3 + button.layer.masksToBounds = true + return button + }() + + let refuseButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setTitle(.refuseText, for: .normal) + button.setBackgroundImage(UIColor.backgroundBlue.trans2Image(), for: .normal) + button.layer.cornerRadius = 3 + button.layer.masksToBounds = true + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.init(0xEBF4FF).cgColor + return button + }() + + // MARK: - 视图生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(contentLabel) + addSubview(welcomeButton) + addSubview(refuseButton) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + contentLabel.snp.makeConstraints { (make) in + make.top.equalToSuperview().offset(8) + make.left.equalToSuperview().offset(20) + } + welcomeButton.snp.makeConstraints { (make) in + make.right.equalTo(snp.centerX).offset(-15) + make.bottom.equalToSuperview().offset(-15) + make.height.equalTo(36) + make.width.equalTo(104) + } + refuseButton.snp.makeConstraints { (make) in + make.left.equalTo(snp.centerX).offset(15) + make.bottom.equalToSuperview().offset(-15) + make.height.equalTo(36) + make.width.equalTo(104) + } + } + + func bindInteraction() { + welcomeButton.addTarget(self, action: #selector(buttonAction(sender:)), for: .touchUpInside) + refuseButton.addTarget(self, action: #selector(buttonAction(sender:)), for: .touchUpInside) + } + + @objc + func buttonAction(sender: UIButton) { + guard let requestInfo = self.currentTakeSeatInfo else { return } + switch sender { + case welcomeButton: + viewModel.acceptTakeSeat(identifier: requestInfo.userID) + case refuseButton: + break; + default: + break + } + viewModel.hideRequestTakeSeatTipsView() + } +} + + +fileprivate extension String { + static let welcomeText = ChatSalonLocalized.getLocalizedString(key: "Welcome") + static let refuseText = ChatSalonLocalized.getLocalizedString(key: "Dismiss") + static let takeSeatSuffix = ChatSalonLocalized.getLocalizedString(key: "applies to become a speaker") +} + +fileprivate extension UIColor { + static let backgroundBlue = UIColor.init(0x0062E3) +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsTableCell.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsTableCell.swift new file mode 100644 index 00000000..6329f6fa --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsTableCell.swift @@ -0,0 +1,145 @@ +// +// TRTCChatSalonTipsTableCell.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCChatSalonTipsTableCell: UITableViewCell { + private var isViewReady: Bool = false + + private var acceptAction: (() -> Void)? + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + backgroundColor = UIColor.clear + selectionStyle = .none + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + let containerView: UIView = { + let view = UIView.init(frame: .zero) + view.backgroundColor = UIColor.init(0x13233F, alpha: 0.4) + view.layer.cornerRadius = 3.0 + return view + }() + + let contentLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.font = UIFont.systemFont(ofSize: 14.0) + label.textColor = UIColor.init(0xEBF4FF) + label.textAlignment = .left + label.numberOfLines = 0 + return label + }() + + let acceptButton: UIButton = { + let button = UIButton.init(type: .custom) + button.setBackgroundImage(UIColor.init(0xE84B40).trans2Image(), for: .normal) + button.setTitle(String.accept, for: .normal) + button.setTitleColor(UIColor.white, for: .normal) + button.isHidden = true + button.layer.cornerRadius = 3.0 + button.layer.masksToBounds = true + return button + }() + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() + activateConstraints() + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + contentView.addSubview(containerView) + containerView.addSubview(contentLabel) + containerView.addSubview(acceptButton) + } + + func activateConstraints() { + contentLabel.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(10) + make.right.equalToSuperview().offset(-10) + make.width.lessThanOrEqualTo(UIScreen.main.bounds.width * 2.0 / 3.0) + make.top.equalToSuperview().offset(10) + make.bottom.equalToSuperview().offset(-10) + } + containerView.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(20) + make.top.equalToSuperview() + make.bottom.equalToSuperview().offset(-10) + } + acceptButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-10) + make.height.equalTo(30) + make.width.equalTo(60) + } + } + + func bindInteraction() { + acceptButton.addTarget(self, action: #selector(acceptAction(sender:)), for: .touchUpInside) + } + + @objc + private func acceptAction(sender: UIButton) { + self.acceptAction?() + } + + func setCell(info: String, action: (() -> Void)?){ + contentLabel.text = info + contentLabel.sizeToFit() + self.acceptAction = action + } + + func updateCell() { + if self.acceptAction != nil { + acceptButton.isHidden = false + // 重新布局 + contentLabel.snp.remakeConstraints { (make) in + make.left.equalToSuperview().offset(10) + make.right.equalToSuperview().offset(-80) + make.width.lessThanOrEqualTo(UIScreen.main.bounds.width * 2.0 / 3.0) + make.top.equalToSuperview().offset(10) + make.bottom.equalToSuperview().offset(-10) + } + } else { + acceptButton.isHidden = true + contentLabel.snp.remakeConstraints { (make) in + make.left.equalToSuperview().offset(10) + make.right.equalToSuperview().offset(-10) + make.width.lessThanOrEqualTo(UIScreen.main.bounds.width * 2.0 / 3.0) + make.top.equalToSuperview().offset(10) + make.bottom.equalToSuperview().offset(-10) + } + } + layoutIfNeeded() + } +} + +fileprivate extension String { + static let accept = ChatSalonLocalized.getLocalizedString(key: "Accept") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsView.swift new file mode 100644 index 00000000..b3a1ffd7 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/SubViews/TRTCChatSalonTipsView.swift @@ -0,0 +1,118 @@ +// +// TRTCChatSalonTipsView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCChatSalonTipsView: UIView { + private var isViewReady: Bool = false + let viewModel: TRTCChatSalonViewModel + + init(frame: CGRect = .zero, viewModel: TRTCChatSalonViewModel) { + self.viewModel = viewModel + super.init(frame: frame) + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + let tipsTableView: UITableView = { + let tableView = UITableView.init(frame: .zero, style: .plain) + tableView.register(TRTCChatSalonTipsTableCell.self, forCellReuseIdentifier: "TRTCChatSalonTipsTableCell") + tableView.backgroundColor = UIColor.clear + tableView.separatorStyle = .none + tableView.estimatedRowHeight = 50 + tableView.rowHeight = UITableView.automaticDimension + return tableView + }() + + // MARK: - 视图生命周期函数 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + addSubview(tipsTableView) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + tipsTableView.snp.makeConstraints { (make) in + make.left.right.bottom.top.equalToSuperview() + } + } + + func bindInteraction() { + tipsTableView.delegate = self + tipsTableView.dataSource = self + } + + func refreshList() { + tipsTableView.reloadData() + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.tipsTableView.scrollToRow(at: IndexPath.init(row: self.viewModel.msgEntityList.count - 1, section: 0), + at: .bottom, + animated: true) + } + } +} + +extension TRTCChatSalonTipsView: UITableViewDelegate { + +} + +extension TRTCChatSalonTipsView: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return viewModel.msgEntityList.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "TRTCChatSalonTipsTableCell", for: indexPath) + if let tipsCell = cell as? TRTCChatSalonTipsTableCell { + let model = viewModel.msgEntityList[indexPath.row] + if model.type == CSMsgEntity.TYPE_NORMAL { + var textInfo = "\(model.content)" + if model.userName.count > 0 { + textInfo = "\(model.userName):\(model.content)" + } + tipsCell.setCell(info: textInfo, action: nil) + } else if model.type == CSMsgEntity.TYPE_AGREED { + tipsCell.setCell(info: "\(model.userName)\(model.content)", action: nil) + } else { + tipsCell.setCell(info: "\(model.userName)\(model.content)") { [weak self] in + guard let `self` = self else { return } + self.viewModel.acceptTakeSeat(identifier: model.userID) + } + } + } + return cell + } + + func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if let tipsCell = cell as? TRTCChatSalonTipsTableCell { + tipsCell.updateCell() + } + } +} + +/// MARK: - internationalization string +fileprivate extension String { + +} + + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonRootView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonRootView.swift new file mode 100644 index 00000000..4df4b502 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonRootView.swift @@ -0,0 +1,675 @@ +// +// TRTCChatSalonRootView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +//Copyright © 2020 tencent. All rights reserved. +// +import UIKit + +class TRTCChatSalonRootView: UIView { + enum TopTipsType { + case requestTakeSeat(CSMemberRequestEntity) + case handsUpSuccess + } + + private class HeaderView: UICollectionReusableView { + private var isViewReady = false + let imageView: UIImageView = { + let view = UIImageView.init(frame: CGRect.zero) + return view + }() + + let titleLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.textColor = .textColor + label.fontSize = 18.0 + return label + }() + + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { return } + addSubview(imageView) + addSubview(titleLabel) + imageView.snp.makeConstraints { (make) in + make.height.width.equalTo(20) + make.left.equalToSuperview() + make.centerY.equalToSuperview() + } + titleLabel.snp.makeConstraints { (make) in + make.left.equalTo(imageView.snp.right).offset(10) + make.centerY.equalTo(imageView.snp.centerY) + } + } + } + + private var isViewReady: Bool = false + let viewModel: TRTCChatSalonViewModel + public weak var rootViewController: UIViewController? + public var alertController: UIAlertController? + + init(frame: CGRect = .zero, viewModel: TRTCChatSalonViewModel) { + self.viewModel = viewModel + super.init(frame: frame) + bindInteraction() + } + + required init?(coder: NSCoder) { + fatalError("can't init this viiew from coder") + } + + let backgroundLayer: CALayer = { + // fillCode + let layer = CAGradientLayer() + layer.colors = [UIColor.init(0x13294b).cgColor, UIColor.init(0x000000).cgColor] + layer.locations = [0.2, 1.0] + layer.startPoint = CGPoint(x: 0.4, y: 0) + layer.endPoint = CGPoint(x: 0.6, y: 1.0) + return layer + }() + + lazy var topTipsView: UIView = { + let view = UIView.init() + view.isHidden = true + view.backgroundColor = UIColor.init(0x0062e3) + return view + }() + + let seatCollection: UICollectionView = { + let layout = UICollectionViewFlowLayout.init() + layout.scrollDirection = .vertical + + let collectionView = UICollectionView.init(frame: .zero, collectionViewLayout: layout) + collectionView.register(TRTCChatSalonSeatCell.self, forCellWithReuseIdentifier: "TRTCChatSalonSeatCell") + collectionView.register(HeaderView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "ChatSalon.HeaderView") + collectionView.backgroundColor = UIColor.clear + return collectionView + }() + + lazy var requestTakeSeatListView: TRTCCSAudienceListView = { + let view = TRTCCSAudienceListView.init(viewModel: viewModel) + view.hide() + return view + }() + + let mainMenuView: UIView = { + let view = UIView.init(frame: .zero) + return view + }() + + // 退房按钮 + let leaveButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setTitle(.leaveText, for: .normal) + button.setBackgroundImage(UIColor.buttonTintColor.trans2Image(), for: .normal) + button.layer.cornerRadius = 3 + button.layer.masksToBounds = true + return button + }() + + // 静音按钮 + let muteButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setImage(.micOn, for: .normal) + button.setImage(.micOff, for: .selected) + return button + }() + + // 下麦按钮 + let leaveSeatButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setImage(.leaveMic, for: .normal) + button.isHidden = true + return button + }() + + // 举手按钮 + let handUpButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setImage(.handsup, for: .selected) + button.setImage(.handsupCancel, for: .normal) + button.isHidden = true + return button + }() + + // 举手列表按钮 + let handUpListButton: UIButton = { + let button = UIButton.init(frame: .zero) + button.setImage(.handsupList, for: .normal) + return button + }() + + let handUpListDot: UILabel = { + let label = UILabel() + label.font = UIFont.systemFont(ofSize: 7) + label.textColor = UIColor.white + label.backgroundColor = UIColor.init(0xE35454) + label.textAlignment = .center + label.layer.cornerRadius = 8 + label.clipsToBounds = true + label.isHidden = true + + return label + }() + + deinit { + TRTCLog.out("reset audio settings") + } + + // MARK: - 视图生命周期 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + backgroundLayer.frame = bounds; + layer.insertSublayer(backgroundLayer, at: 0) + addSubview(topTipsView) + addSubview(seatCollection) + addSubview(mainMenuView) + mainMenuView.addSubview(leaveSeatButton) + mainMenuView.addSubview(muteButton) + mainMenuView.addSubview(leaveButton) + mainMenuView.addSubview(handUpButton) + mainMenuView.addSubview(handUpListButton) + mainMenuView.addSubview(handUpListDot) + addSubview(requestTakeSeatListView) + } + + func activateConstraints() { + /// 此方法内只给子视图做布局,使用:AutoLayout布局 + activateConstraintsOfCustomSeatArea() + activateConstraintsOfMainMenu() + activateConstraintsOfAudiceneList() + } + + func bindInteraction() { + seatCollection.delegate = self + seatCollection.dataSource = self + /// 此方法负责做viewModel和视图的绑定操作 + muteButton.addTarget(self, action: #selector(mainMenuButtonAction(sender:)), for: .touchUpInside) + handUpButton.addTarget(self, action: #selector(mainMenuButtonAction(sender:)), for: .touchUpInside) + leaveSeatButton.addTarget(self, action: #selector(mainMenuButtonAction(sender:)), for: .touchUpInside) + handUpListButton.addTarget(self, action: #selector(mainMenuButtonAction(sender:)), for: .touchUpInside) + leaveButton.addTarget(self, action: #selector(mainMenuButtonAction(sender:)), for: .touchUpInside) + } +} + + +// MARK: - collection view delegate +extension TRTCChatSalonRootView: UICollectionViewDelegateFlowLayout { + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + if (indexPath.section == 0) { + return CGSize(width: 80, height: 112) + } else { + return CGSize(width: 60, height: 92) + } + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { + return UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0) + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { + return 30 + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { + if (section == 0) { + return (UIScreen.main.bounds.width - 40 - 80 * 3) / 2.0 + } else { + return (UIScreen.main.bounds.width - 40 - 60 * 4) / 3.0 + } + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + if indexPath.section != 0 || !viewModel.isOwner { + return + } + if indexPath.row > 0 { + let index = viewModel.anchorSeatList.index(viewModel.anchorSeatList.startIndex, offsetBy: indexPath.row - 1) + if index >= viewModel.anchorSeatList.startIndex && index <= viewModel.anchorSeatList.endIndex { + let (_, model) = viewModel.anchorSeatList[index] + model.action?(model) // 转换座位号输入 + } + } + } + + func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { + if kind == UICollectionView.elementKindSectionHeader { + let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, + withReuseIdentifier: "ChatSalon.HeaderView", + for: indexPath) + if let header = view as? HeaderView { + header.titleLabel.text = indexPath.section == 0 ? .anchorHeaderText : .audienceHeaderText + header.imageView.image = indexPath.section == 0 ? UIImage.anchorHeaderIcon : UIImage.audienceHeaderIcon + } + return view + } else { + return UICollectionReusableView.init() + } + } + + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + return CGSize.init(width: UIScreen.main.bounds.width, height: 30) + } +} + +extension TRTCChatSalonRootView: UICollectionViewDataSource { + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 2; + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + if section == 0 { + return viewModel.anchorUserIDs.count + 1 + } else { + return viewModel.memberAudienceDic.count + } + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TRTCChatSalonSeatCell", for: indexPath) + if let seatCell = cell as? TRTCChatSalonSeatCell { + // 配置 seatCell 信息 + if indexPath.section == 0 { + if indexPath.row == 0 { + guard let masterAnchor = viewModel.masterAnchor else { return seatCell } + seatCell.setCell(model: masterAnchor) + } else { + let anchorID = viewModel.anchorUserIDs[indexPath.row - 1] + guard let model = viewModel.anchorSeatList[anchorID] else { return cell } + seatCell.setCell(model: model) + } + + } else { + let index = viewModel.memberAudienceDic.index(viewModel.memberAudienceDic.startIndex, offsetBy: indexPath.row) + let (_, audience) = viewModel.memberAudienceDic[index] + seatCell.setCell(audience: audience) + } + } + return cell + } + + +} + +extension TRTCChatSalonRootView { + func activateConstraintsOfCustomSeatArea() { + topTipsView.snp.makeConstraints { (make) in + make.left.right.equalToSuperview() + if #available(iOS 11.0, *) { + make.top.equalTo(safeAreaLayoutGuide.snp.top) + } else { + // Fallback on earlier versions + make.top.equalToSuperview().offset(64) + } + make.height.equalTo(0) + } + seatCollection.snp.makeConstraints { (make) in + make.top.equalTo(topTipsView.snp.bottom) + make.left.equalToSuperview().offset(20) + make.right.equalToSuperview().offset(-20) + make.bottom.equalTo(mainMenuView.snp.top) + } + } + + func activateConstraintsOfMainMenu() { + mainMenuView.snp.makeConstraints { (make) in + make.left.right.equalToSuperview() + make.height.equalTo(48) + if #available(iOS 11.0, *) { + make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom).offset(-20) + } else { + // Fallback on earlier versions + make.bottom.equalToSuperview().offset(-20) + } + } + leaveButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(20) + make.height.equalTo(36) + make.width.equalTo(144) + } + // 主播观众公有 + muteButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-20) + make.height.width.equalTo(48) + } + // 主播端 + handUpListButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.right.equalTo(muteButton.snp.left).offset(-20) + make.height.width.equalTo(48) + } + handUpListDot.snp.makeConstraints { (make) in + make.right.top.equalTo(handUpListButton) + make.height.equalTo(16) + make.width.greaterThanOrEqualTo(16) + } + // 观众端 + handUpButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-20) + make.height.width.equalTo(48) + } + leaveSeatButton.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.right.equalTo(muteButton.snp.left).offset(-20) + make.height.width.equalTo(48) + } + + } + + func activateConstraintsOfAudiceneList() { + requestTakeSeatListView.snp.makeConstraints { (make) in + make.top.left.bottom.right.equalToSuperview() + } + } +} + +extension TRTCChatSalonRootView { + @objc + private func mainMenuButtonAction(sender: UIButton) { + switch sender { + case handUpButton: + + viewModel.startTakeSeat(seatIndex: 0) + case muteButton: + muteButton.isSelected = !muteButton.isSelected + let _ = viewModel.muteAction(isMute: muteButton.isSelected) // 返回值为false说明无法调整麦克风 + case leaveButton: + if viewModel.roomType == .anchor && viewModel.isOwner { + showAlert(info: (title: "", message: .ownerExitMsg), actionTitle: (sure: .sureActionTitle, cancel: .cancelActionTitle)) { [weak self] in + guard let `self` = self else { return } + self.viewModel.exitRoom() // 主播销毁房间 + } cancelAction: { + + } + } else { + showAlert(info: (title: "", message: .alertAudienceTitle), actionTitle: (sure: .alertAudienceConfirm, cancel: .alertAudienceCancel)) { [weak self] in + guard let `self` = self else { return } + self.viewModel.exitRoom() + } cancelAction: { + + } + } + case handUpListButton: + viewModel.openRequestTakeSeatList(isOpen: true) + break + case leaveSeatButton: + viewModel.leaveSeatAction() + default: + break + } + + } + + private func showAlert(info: (title: String, message: String), + actionTitle: (sure: String, cancel: String), + sureAction: @escaping () -> Void, + cancelAction: (() -> Void)?) { + if let alert = alertController { + alert.dismiss(animated: false) { [weak self] in + guard let `self` = self else { return } + self.alertController = nil + } + } + let alertController = UIAlertController.init(title: info.title, message: info.message, preferredStyle: .alert) + let sureAlertAction = UIAlertAction.init(title: actionTitle.sure, style: .default) { (action) in + sureAction() + alertController.dismiss(animated: false) { [weak self] in + guard let `self` = self else { return } + self.alertController = nil + } + } + let cancelAlertAction = UIAlertAction.init(title: actionTitle.cancel, style: .cancel) { (action) in + cancelAction?() + alertController.dismiss(animated: false) { [weak self] in + guard let `self` = self else { return } + self.alertController = nil + } + } + alertController.addAction(sureAlertAction) + alertController.addAction(cancelAlertAction) + rootViewController?.present(alertController, animated: false, completion: { [weak self] in + guard let `self` = self else { return } + self.alertController = alertController + }) + } + + func showTopTips(type: TopTipsType) { + let innerView: UIView + let height: CGFloat + switch type { + case .requestTakeSeat(let info): + let tipsView = TRTCChatSalonTakeSeatTipsView.init(frame: .zero, viewModel: viewModel) + tipsView.currentTakeSeatInfo = info + innerView = tipsView + height = TRTCChatSalonTakeSeatTipsView.kHeight + case .handsUpSuccess: + innerView = TRTCChatSalonHandsUpTipsView() + height = TRTCChatSalonHandsUpTipsView.kHeight + } + topTipsView.addSubview(innerView) + innerView.snp.makeConstraints { (make) in + make.left.right.top.bottom.equalToSuperview() + } + + topTipsView.isHidden = false + topTipsView.snp.updateConstraints { (make) in + make.height.equalTo(height) + } + + layoutIfNeeded() + } + + func hideTopTips() { + topTipsView.isHidden = true + topTipsView.snp.updateConstraints { (make) in + make.height.equalTo(0) + } + for subview in topTipsView.subviews { + subview.removeFromSuperview() + } + layoutIfNeeded() + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + if requestTakeSeatListView.isHidden { + super.touchesBegan(touches, with: event) + return + } + guard let touch = touches.first else { + return + } + let point = touch.location(in: self) + if !requestTakeSeatListView.frame.contains(point) { + viewModel.openRequestTakeSeatList(isOpen: false) + } + } +} + +extension TRTCChatSalonRootView: TRTCChatSalonViewResponder { + func showAlert(info: (title: String, message: String), sureAction: @escaping () -> Void, cancelAction: (() -> Void)?) { + self.showAlert(info: info, actionTitle: (sure: .acceptTitle, cancel: .refuseTitle), sureAction: sureAction, cancelAction: cancelAction) + } + + func refreshTakeSeatList() { + requestTakeSeatListView.refreshList() + updateHandUpListDot() + } + + func showRequestTakeSeatTips(request: CSMemberRequestEntity?) { + // 显示最新的上麦申请 + guard let requestMsg = request else { + hideTopTips() + return + } + showTopTips(type: .requestTakeSeat(requestMsg)) + } + + func showHandUpTips(isShow: Bool) { + if isShow { + showTopTips(type: .handsUpSuccess) + DispatchQueue.main.asyncAfter(deadline: .now() + 10) { [weak self] in + guard let self = self else { return } + self.viewModel.isHandUp = false + self.hideTopTips() + } + } else { + hideTopTips() + } + } + + func msgInput(show: Bool) { + } + + func showAudioEffectView() { + } + + func stopPlayBGM() { + } + + func recoveryVoiceSetting() { + } + + + func audienceListRefresh() { + seatCollection.reloadSections(IndexSet.init(integer: 1)) + } + + func onSeatMute(isMute: Bool) { + if isMute { + makeToast(String.seatMute, duration: 0.3) + } else { + makeToast(String.seatUnmute, duration: 0.3) + if viewModel.isSelfMute { + return; + } + } + } + + func showActionSheet(actionTitles: [String], actions: @escaping (Int) -> Void) { + let actionSheet = UIAlertController.init(title: String.chooseTitle, message: "", preferredStyle: .actionSheet) + actionTitles.enumerated().forEach { (item) in + let index = item.offset + let title = item.element + let action = UIAlertAction.init(title: title, style: UIAlertAction.Style.default) { (action) in + actions(index) + actionSheet.dismiss(animated: true, completion: nil) + } + actionSheet.addAction(action) + } + let cancelAction = UIAlertAction.init(title: String.cancelActionTitle, style: .cancel) { (action) in + actionSheet.dismiss(animated: true, completion: nil) + } + actionSheet.addAction(cancelAction) + rootViewController?.present(actionSheet, animated: true, completion: nil) + } + + func showToast(message: String) { + makeToast(message, duration: 1.0) + } + + func popToPrevious() { + rootViewController?.navigationController?.popViewController(animated: true) + } + + func switchView(type: ChatSalonViewType) { + switch type { + case .audience: + muteButton.isHidden = true + handUpButton.isHidden = false + leaveSeatButton.isHidden = true + handUpListButton.isHidden = true + handUpListDot.isHidden = true + break + case .anchor: + muteButton.isHidden = false + handUpButton.isHidden = true + if viewModel.isOwner { + leaveSeatButton.isHidden = true + handUpListButton.isHidden = false + updateHandUpListDot() + } else { + handUpListButton.isHidden = true + handUpListDot.isHidden = true + leaveSeatButton.isHidden = false + // 这里需要在观众端上麦时,同步按钮状态 + muteButton.isSelected = false + let _ = viewModel.muteAction(isMute: muteButton.isSelected, needShowToast: false) // 返回值为false说明无法调整麦克风权限 + } + break + } + } + + func changeRoom(title: String) { + rootViewController?.title = title + } + + func refreshAnchorInfos() { + seatCollection.reloadData() + } + + func reuqestTakeSeatList(show: Bool) { + if show { + requestTakeSeatListView.show() + } else { + requestTakeSeatListView.hide() + } + } + + func updateHandUpListDot() { + if viewModel.requestTakeSeatMap.count == 0 { + handUpListDot.isHidden = true + } else { + handUpListDot.isHidden = false + handUpListDot.text = String(viewModel.requestTakeSeatMap.count) + } + } +} + +/// MARK: - internationalization string +fileprivate extension String { + static let anchorHeaderText = ChatSalonLocalized.getLocalizedString(key: "speakers") + static let audienceHeaderText = ChatSalonLocalized.getLocalizedString(key: "audiences") + static let leaveText = ChatSalonLocalized.getLocalizedString(key: "Leave quietly") + static let sureActionTitle = ChatSalonLocalized.getLocalizedString(key: "Owner.Confirm") + static let cancelActionTitle = ChatSalonLocalized.getLocalizedString(key: "Cancel") + static let acceptTitle = ChatSalonLocalized.getLocalizedString(key: "Welcome") + static let refuseTitle = ChatSalonLocalized.getLocalizedString(key: "Dismiss") + static let ownerExitMsg = ChatSalonLocalized.getLocalizedString(key: "you want to end the room?") + static let seatMute = ChatSalonLocalized.getLocalizedString(key: "Seat.Muted") + static let seatUnmute = ChatSalonLocalized.getLocalizedString(key: "Seat.Unmuted") + static let chooseTitle = ChatSalonLocalized.getLocalizedString(key: "Please select") + + static let alertAudienceTitle = ChatSalonLocalized.getLocalizedString(key: "You want to leave the room?") + static let alertAudienceConfirm = ChatSalonLocalized.getLocalizedString(key: "Audience.Confirm") + static let alertAudienceCancel = ChatSalonLocalized.getLocalizedString(key: "Wait a bit") +} + +fileprivate extension UIColor { + static let textColor = UIColor.init(0xEBF4FF) // 文本颜色 + static let buttonTintColor = UIColor.init(0x0062e3) // 按钮颜色 +} + +fileprivate extension UIImage { + static let anchorHeaderIcon = UIImage.init(named: "chatsalon_anchor") + static let audienceHeaderIcon = UIImage.init(named: "chatsalon_audience") + static let micOff = UIImage.init(named: "chatsalon_mic_off") + static let micOn = UIImage.init(named: "chatsalon_mic_on") + static let leaveMic = UIImage.init(named: "chatsalon_leave_mic") + static let handsup = UIImage.init(named: "chatsalon_handsup") + static let handsupCancel = UIImage.init(named: "chatsalon_handsup_cancel") + static let handsupList = UIImage.init(named: "chatsalon_handsup_list") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonVIewDataDef.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonVIewDataDef.swift new file mode 100644 index 00000000..8b5155d3 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonVIewDataDef.swift @@ -0,0 +1,76 @@ +// +// TRTCChatSalonModelDef.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/15. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +enum ChatSalonViewType { + case anchor + case audience +} + +/// Voice Room 定义常量的类 +class ChatSalonConstants { + public static let TYPE_VOICE_ROOM = "chatSalon" + // 直播端右下角listview显示的type + public static let CMD_REQUEST_TAKE_SEAT = "1" + public static let CMD_PICK_UP_SEAT = "2" +} + +/// 记录房间座位信息的Model +struct ChatSalonSeatInfoModel { + var seatIndex: Int = -1 + var isClosed: Bool = false + var isUsed: Bool = false + var isOwner: Bool = false + var seatInfo: ChatSalonSeatInfo? + var seatUser: ChatSalonUserInfo? + var action: ((ChatSalonSeatInfoModel) -> Void)? // 入参为当前Model对象 + var isTalking = false +} + +/// 记录房间消息列表的Model +struct CSMsgEntity { + public static let TYPE_NORMAL = 0; + public static let TYPE_WAIT_AGREE = 1; + public static let TYPE_AGREED = 2; + + let userID: String + let userName: String + let content: String + let invitedId: String + var type: Int +} + +/// 记录房间上麦申请的Model +struct CSMemberRequestEntity { + public static let TYPE_WAIT_AGREE = 1; + public static let TYPE_AGREED = 2; + + let userID: String + var userInfo: ChatSalonUserInfo + let content: String + var invitedId: String + var type: Int + var action: (Int) -> Void // 点击同意上麦按钮的动作 +} + +struct CSAudienceInfoModel { + + static let TYPE_IDEL = 0 + static let TYPE_IN_SEAT = 1 + static let TYPE_WAIT_AGREE = 2 + + var type: Int = 0 // 观众类型 + var userInfo: ChatSalonUserInfo + var action: (Int) -> Void // 点击邀请按钮的动作 +} + +struct CSSeatInvitation { + let seatIndex: Int + let inviteUserId: String +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewController.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewController.swift new file mode 100644 index 00000000..adaa5fec --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewController.swift @@ -0,0 +1,104 @@ +// +// TRTCChatSalonViewController.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +//Copyright © 2020 tencent. All rights reserved. +// +import UIKit + +protocol TRTCChatSalonViewModelFactory { + func makeChatSalonViewModel(roomInfo: ChatSalonInfo, roomType: ChatSalonViewType) -> TRTCChatSalonViewModel +} + +/// TRTC voice room 聊天室 +public class TRTCChatSalonViewController: UIViewController { + // MARK: - properties: + let viewModelFactory: TRTCChatSalonViewModelFactory + let roomInfo: ChatSalonInfo + let role: ChatSalonViewType + var viewModel: TRTCChatSalonViewModel? + let toneQuality: ChatSalonToneQuality + // MARK: - Methods: + init(viewModelFactory: TRTCChatSalonViewModelFactory, roomInfo: ChatSalonInfo, role: ChatSalonViewType, toneQuality: ChatSalonToneQuality = .music) { + self.viewModelFactory = viewModelFactory + self.roomInfo = roomInfo + self.role = role + self.toneQuality = toneQuality + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - life cycle + public override func viewDidLoad() { + super.viewDidLoad() + title = "\(roomInfo.roomName)\(roomInfo.roomID)" + let backItem = UIBarButtonItem.init(image: UIImage.init(named: "navigationbar_back"), style: .plain, target: self, action: #selector(cancel)) + self.navigationItem.leftBarButtonItem = backItem + guard let model = viewModel else { return } + if model.roomType == .audience { + model.enterRoom() + } else { + model.createRoom(toneQuality: toneQuality.rawValue) + } + } + + public override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + viewModel?.refreshView() + } + + public override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + } + + public override func loadView() { + // Reload view in this function + let viewModel = viewModelFactory.makeChatSalonViewModel(roomInfo: roomInfo, roomType: role) + let rootView = TRTCChatSalonRootView.init(viewModel: viewModel) + rootView.rootViewController = self + viewModel.viewResponder = rootView + self.viewModel = viewModel + view = rootView + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + /// 取消 + @objc func cancel() { + presentAlert(title: "", message: String.alertTitle) { [weak self] in + guard let `self` = self else { return } + self.viewModel?.exitRoom() // 主播销毁房间 + } + } +} + +extension TRTCChatSalonViewController { + func presentAlert(title: String, message: String, sureAction:@escaping () -> Void) { + let alertVC = UIAlertController.init(title: title, message: message, preferredStyle: .alert) + let alertOKAction = UIAlertAction.init(title: String.alertConfirm, style: .default) { (action) in + alertVC.dismiss(animated: true, completion: nil) + sureAction() + } + let alertCancelAction = UIAlertAction.init(title: String.alertCancel, style: .cancel) { (action) in + alertVC.dismiss(animated: true, completion: nil) + } + alertVC.addAction(alertCancelAction) + alertVC.addAction(alertOKAction) + present(alertVC, animated: true, completion: nil) + } +} + +private extension String { + static let controllerTitle = ChatSalonLocalized.getLocalizedString(key: "room ID") + static let alertTitle = ChatSalonLocalized.getLocalizedString(key: "You want to leave the room?") + static let alertConfirm = ChatSalonLocalized.getLocalizedString(key: "Audience.Confirm") + static let alertCancel = ChatSalonLocalized.getLocalizedString(key: "Wait a bit") +} + + diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewModel.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewModel.swift new file mode 100644 index 00000000..3f20e13d --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCChatSalonViewController/TRTCChatSalonViewModel.swift @@ -0,0 +1,799 @@ +// +// TRTCChatSalonViewModel.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +// Copyright © 2020 tencent. All rights reserved. +// + +import Foundation + +protocol TRTCChatSalonViewResponder: class { + func showToast(message: String) + func popToPrevious() + func switchView(type: ChatSalonViewType) + func changeRoom(title: String) + func refreshAnchorInfos() + func onSeatMute(isMute: Bool) + func showAlert(info: (title: String, message: String), sureAction: @escaping () -> Void, cancelAction: (() -> Void)?) + func showActionSheet(actionTitles:[String], actions: @escaping (Int) -> Void) + func refreshTakeSeatList() + func showRequestTakeSeatTips(request: CSMemberRequestEntity?) + func showHandUpTips(isShow: Bool) + func msgInput(show: Bool) + func reuqestTakeSeatList(show: Bool) + func audienceListRefresh() + func showAudioEffectView() + func stopPlayBGM() // 停止播放音乐 + func recoveryVoiceSetting() // 恢复音效设置 +} + +class TRTCChatSalonViewModel: NSObject { + private let dependencyContainer: TRTCChatSalonEnteryControl + private(set) var roomType: ChatSalonViewType { + didSet { + roleChange(viewType: roomType) + } + } + public weak var viewResponder: TRTCChatSalonViewResponder? + + private(set) var isSelfMute: Bool = false + // 防止多次退房 + private var isExitingRoom: Bool = false + + private(set) var roomInfo: ChatSalonInfo + private(set) var isSeatInitSuccess: Bool = false + private(set) var mSelfSeatIndex: Int = -1 + private(set) var isOwnerMute: Bool = false + /// 是否是房主 + public var isOwner: Bool { + return dependencyContainer.userID == roomInfo.ownerId // 是否是房主 + } + + // UI相关属性 + private(set) var masterAnchor: ChatSalonSeatInfoModel? + private(set) var anchorUserIDs: [String] = [] + private(set) var anchorSeatList: [String : ChatSalonSeatInfoModel] = [:] + /// 观众信息记录 + private(set) var memberAudienceDic: [String: CSAudienceInfoModel] = [:] + /// 上麦申请记录 + var requestTakeSeatMap: [String: CSMemberRequestEntity] = [:] + /// 是否举手 + public var isHandUp: Bool = false + + private(set) var msgEntityList: [CSMsgEntity] = [] + /// 当前邀请操作的座位号记录 + private var currentInvitateSeatIndex: Int = -1 // -1 表示没有操作 + private var currentRequestTipsEntity: CSMemberRequestEntity? // 当前tips + /// 上麦信息记录(观众端) + private var mInvitationSeatDic: [String: Int] = [:] + /// 上麦信息记录(主播端) + private var mTakeCSSeatInvitationDic: [String: String] = [:] + /// 抱麦信息记录 + private var mPickCSSeatInvitationDic: [String: CSSeatInvitation] = [:] + + + /// 房间管理对象 + private var chatSalonManager: TRTCChatSalonManager { + return TRTCChatSalonManager.shared + } + + /// 初始化方法 + /// - Parameter container: 依赖管理容器,负责ChatSalon模块的依赖管理 + init(container: TRTCChatSalonEnteryControl, roomInfo: ChatSalonInfo, roomType: ChatSalonViewType) { + self.dependencyContainer = container + self.roomType = roomType + self.roomInfo = roomInfo + super.init() + chatSalon.setDelegate(delegate: self) + roleChange(viewType: self.roomType) + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + private var chatSalon: TRTCChatSalon { + return dependencyContainer.getChatSalon() + } + + func exitRoom() { + guard !isExitingRoom else { return } + viewResponder?.popToPrevious() + isExitingRoom = true + if dependencyContainer.userID == roomInfo.ownerId && roomType == .anchor { + chatSalonManager.destroyRoom(sdkAppID: dependencyContainer.mSDKAppID, roomID: "\(roomInfo.roomID)", success: { + TRTCLog.out("---destroy room success.") + }) { (code, message) in + TRTCLog.out("---destroy room failed.") + } + chatSalon.destroyRoom { [weak self] (code, message) in + guard let `self` = self else { return } + self.isExitingRoom = false + } + return + } + chatSalon.exitRoom { [weak self] (code, message) in + guard let `self` = self else { return } + self.isExitingRoom = false + } + } + + public func refreshView() { + roleChange(viewType: roomType) + } + + public func openMessageTextInput() { + viewResponder?.msgInput(show: true) + } + + public func openAudioEffectMenu() { + guard checkButtonPermission() else { return } + viewResponder?.showAudioEffectView() + } + + public func openRequestTakeSeatList(isOpen: Bool) { + viewResponder?.reuqestTakeSeatList(show:isOpen) + } + + public func muteAction(isMute: Bool, needShowToast: Bool = true) -> Bool { + guard checkButtonPermission() else { return false } + isSelfMute = isMute + chatSalon.muteLocalAudio(mute: isMute) + if isMute { + viewResponder?.stopPlayBGM() + if needShowToast { + viewResponder?.showToast(message: .closedMicText) + } + } else { + viewResponder?.recoveryVoiceSetting() + if needShowToast { + viewResponder?.showToast(message: .openedMicText) + } + } + return true + } + + public func spechAction(isMute: Bool) { +// chatSalon.muteAllRemoteAudio(isMute: isMute) +// if isMute { +// viewResponder?.showToast(message: "TODO") +// } else { +// viewResponder?.showToast(message: "TODO") +// } + } + + public func clickSeat(model: ChatSalonSeatInfoModel) { + guard isSeatInitSuccess else { + viewResponder?.showToast(message: .micInitNotReadyText) + return + } + if roomType == .audience || !isOwner { + audienceClickItem(model: model) + } else { + anchorClickItem(model: model) + } + } + + public func leaveSeatAction() { + guard !isOwner else { return } + leaveSeat() // 下麦 + } + + public func enterRoom(toneQuality: Int = ChatSalonToneQuality.music.rawValue) { + chatSalon.enterRoom(roomID: roomInfo.roomID) { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.showToast(message: .enterRoomSuccText) + self.getAudienceList() + self.chatSalon.setAuidoQuality(quality: toneQuality) + } else { + self.viewResponder?.showToast(message: .enterRoomFailText) + self.viewResponder?.popToPrevious() + } + } + } + + public func createRoom(toneQuality: Int = 0) { + var coverUrl = roomInfo.coverUrl + if !coverUrl.hasPrefix("http") { + coverUrl = ProfileManager.shared.curUserModel?.avatar ?? "" + } + chatSalon.setAuidoQuality(quality: toneQuality) + chatSalon.setSelfProfile(userName: roomInfo.ownerName, avatarURL: coverUrl) { [weak self] (code, message) in + guard let `self` = self else { return } + TRTCLog.out("setSelfProfile\(code)\(message)") + TRTCChatSalonManager.shared.createRoom(sdkAppID: SDKAPPID, roomID: "\(self.roomInfo.roomID)", success: { [weak self] in + guard let `self` = self else { return } + self.internalCreateRoom() + }) { [weak self] (code, message) in + guard let `self` = self else { return } + if code == -1301 { + self.internalCreateRoom() + } else { + self.viewResponder?.showToast(message: .createRoomFailedText) + self.viewResponder?.popToPrevious() + } + } + } + } + + public func onTextMsgSend(message: String) { +// if message.count == 0 { +// return +// } +// // 消息回显示 +// let entity = CSMsgEntity.init(userID: dependencyContainer.userID, userName: "TODO", content: message, invitedId: "", type: CSMsgEntity.TYPE_NORMAL) +// notifyMsg(entity: entity) +// chatSalon.sendRoomTextMsg(message: message) { [weak self] (code, message) in +// guard let `self` = self else { return } +// self.viewResponder?.showToast(message: code == 0 ? "TODO" : "TODO:\(message)") +// } + } + + /// 同意上麦 + /// - Parameter identifier: 上麦的id + public func acceptTakeSeat(identifier: String) { + if let audience = memberAudienceDic[identifier] { + acceptTakeSeatInviattion(userInfo: audience.userInfo) + } + } + + public func hideRequestTakeSeatTipsView() { + currentRequestTipsEntity = nil + viewResponder?.showRequestTakeSeatTips(request: nil) + } + + /// 观众开始上麦 + public func startTakeSeat(seatIndex: Int) { + if roomType == .anchor { + viewResponder?.showToast(message: .alreadyIsAnchorText) + return + } + + // 需要申请上麦 + guard roomInfo.ownerId != "" else { + viewResponder?.showToast(message: .roomNotReadyText) + return + } + guard !isHandUp else { + viewResponder?.showToast(message: .waitHostAcceptText) + return + } + self.isHandUp = true + let cmd = ChatSalonConstants.CMD_REQUEST_TAKE_SEAT + let targetUserId = roomInfo.ownerId + let inviteId = chatSalon.sendInvitation(cmd: cmd, userID: targetUserId, content: "\(seatIndex)") { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.showHandUpTips(isShow: true) + } else { + self.viewResponder?.showToast(message: "\(String.takeSeatSendFailed)\(message)") + self.isHandUp = false + } + } + mInvitationSeatDic[inviteId] = seatIndex + } +} + +// MARK: - private method +extension TRTCChatSalonViewModel { + + private func internalCreateRoom() { + let param = ChatSalonParam.init() + param.roomName = roomInfo.roomName + param.needRequest = roomInfo.needRequest + param.coverUrl = roomInfo.coverUrl + param.seatInfoList = [] + chatSalon.createRoom(roomID: Int32(roomInfo.roomID), roomParam: param) { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.changeRoom(title: "\(self.roomInfo.roomName)(\(self.roomInfo.roomID))") + self.takeMainSeat() + self.getAudienceList() + } else { + self.viewResponder?.showToast(message: .enterRoomFailText) + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in + guard let `self` = self else { return } + self.viewResponder?.popToPrevious() + } + } + } + } + + private func takeMainSeat() { + chatSalon.enterSeat { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.showToast(message: .masterOnSeatSuccess) + } else { + self.viewResponder?.showToast(message: .masterOnSeatFailed) + } + } + } + + private func getAudienceList() { + chatSalon.getUserInfoList(userIDList: nil) { [weak self] (code, message, infos) in + guard let `self` = self else { return } + if code == 0 { + self.memberAudienceDic.removeAll() + let audienceInfoModels = infos.map { (userInfo) -> CSAudienceInfoModel in + return CSAudienceInfoModel.init(userInfo: userInfo) { [weak self] (index) in + // 点击邀请上麦事件,以及接受邀请事件 + guard let `self` = self else { return } + if index == 0 { + self.sendInvitation(userInfo: userInfo) + } else { + self.acceptTakeSeatInviattion(userInfo: userInfo) + } + } + }.filter { (model) -> Bool in + return !self.anchorSeatList.keys.contains(model.userInfo.userID) + } + audienceInfoModels.forEach { (info) in + self.memberAudienceDic[info.userInfo.userID] = info + } + self.viewResponder?.audienceListRefresh() + } + } + } + + func checkButtonPermission() -> Bool { + if roomType == .audience { + viewResponder?.showToast(message: .onlyAnchorUse) + return false + } + return true + } + + private func roleChange(viewType: ChatSalonViewType) { + viewResponder?.switchView(type: viewType) + } + + private func audienceClickItem(model: ChatSalonSeatInfoModel) { + // TODO: audience click item action. + } + + private func anchorClickItem(model: ChatSalonSeatInfoModel) { + guard !model.isOwner else { return } + if model.isUsed { + viewResponder?.showActionSheet(actionTitles: [.kickOutMicText], actions: { [weak self] (index) in + guard let `self` = self,let userID = model.seatUser?.userID else { return } + if index == 0 { + // 下麦 + self.chatSalon.kickSeat(userID: userID, callback: nil) + } + }) + return + } + } + + private func onAnchorSeatSelected(seatIndex: Int) { + viewResponder?.reuqestTakeSeatList(show: true) + currentInvitateSeatIndex = seatIndex + } + + private func sendInvitation(userInfo: ChatSalonUserInfo) { + // TODO: - invitation someone on mic. + } + + private func acceptTakeSeatInviattion(userInfo: ChatSalonUserInfo) { + // 接受 + guard let inviteID = mTakeCSSeatInvitationDic[userInfo.userID] else { + viewResponder?.showToast(message: .inviatttionTimeoutText) + return + } + chatSalon.acceptInvitation(identifier: inviteID) { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + // 接受请求成功,刷新外部对话列表 + self.requestTakeSeatMap.removeValue(forKey: userInfo.userID) + self.viewResponder?.refreshTakeSeatList() + } else { + self.viewResponder?.showToast(message: .acceptInvitationFailed) + } + } + } + + private func leaveSeat() { + chatSalon.leaveSeat { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.showToast(message: .leaveSeatSuccText) + } else { + self.viewResponder?.showToast(message: "\(String.leaveSeatFailedText)\(message)") + } + } + } + + private func recvPickSeat(identifier: String, cmd: String, content: String) { + // TODO: recvice pick seat. + } + + private func recvTakeSeat(identifier: String, inviter: String, content: String) { + let audinece = memberAudienceDic[inviter] + // 收到新的邀请后,更新列表,其他的信息 + if let memberEntity = requestTakeSeatMap[inviter] { + // 已经在申请上麦了, 更新请求ID + var newEntity = memberEntity + newEntity.invitedId = identifier + requestTakeSeatMap[inviter] = newEntity + } else { + if let userInfo = audinece?.userInfo { + let msgEntity = CSMemberRequestEntity.init(userID: inviter, userInfo: userInfo, content: "", invitedId: identifier, type: CSMemberRequestEntity.TYPE_WAIT_AGREE) { [weak self] (index) in + guard let `self` = self else { return } + guard index == 0 else { return } + if let currentTips = self.currentRequestTipsEntity { + if currentTips.userID == userInfo.userID { + self.hideRequestTakeSeatTipsView() + } + } + self.acceptTakeSeat(identifier: userInfo.userID) + self.openRequestTakeSeatList(isOpen: false) + } + requestTakeSeatMap[inviter] = msgEntity + currentRequestTipsEntity = msgEntity + viewResponder?.showRequestTakeSeatTips(request: msgEntity) + } + } + viewResponder?.refreshTakeSeatList() + if var audienceModel = audinece { + audienceModel.type = CSAudienceInfoModel.TYPE_WAIT_AGREE + memberAudienceDic[audienceModel.userInfo.userID] = audienceModel + viewResponder?.audienceListRefresh() + } + mTakeCSSeatInvitationDic[inviter] = identifier + } + + private func notifyMsg(entity: CSMsgEntity) { + DispatchQueue.main.async { [weak self] in + guard let `self` = self else { return } + if self.msgEntityList.count > 1000 { + self.msgEntityList.removeSubrange(0...99) + } + self.msgEntityList.append(entity) + self.viewResponder?.refreshTakeSeatList() + } + } + + private func showNotifyMsg(messsage: String) { + let msgEntity = CSMsgEntity.init(userID: "", userName: "", content: messsage, invitedId: "", type: CSMsgEntity.TYPE_NORMAL) + if msgEntityList.count > 1000 { + msgEntityList.removeSubrange(0...99) + } + msgEntityList.append(msgEntity) + viewResponder?.refreshTakeSeatList() + } + + private func changeAudience(status: Int, user: ChatSalonUserInfo) { + guard [CSAudienceInfoModel.TYPE_IDEL, CSAudienceInfoModel.TYPE_IN_SEAT, CSAudienceInfoModel.TYPE_WAIT_AGREE].contains(status) else { return } + let audience = memberAudienceDic[user.userID] + if status == CSAudienceInfoModel.TYPE_IN_SEAT { + memberAudienceDic.removeValue(forKey: user.userID) + } else { + if var audienceModel = audience { + if audienceModel.type == status { return } + audienceModel.type = status + memberAudienceDic[audienceModel.userInfo.userID] = audienceModel + } else { + if status != CSAudienceInfoModel.TYPE_IN_SEAT { + let audienceModel = CSAudienceInfoModel.init(type: status, userInfo: user) { (index) in + + } + memberAudienceDic[user.userID] = audienceModel + } + } + } + viewResponder?.audienceListRefresh() + } +} + +// MARK:- room delegate +extension TRTCChatSalonViewModel: TRTCChatSalonDelegate { + func onError(code: Int32, message: String) { + + } + + func onWarning(code: Int32, message: String) { + + } + + func onDebugLog(message: String) { + + } + + func onRoomDestroy(message: String) { + viewResponder?.showToast(message: .hostDestroyRoomText) + chatSalon.exitRoom(callback: nil) + viewResponder?.popToPrevious() + } + + func onRoomInfoChange(roomInfo: ChatSalonInfo) { + // 值为-1表示该接口没有返回数量信息 + if roomInfo.memberCount == -1 { + roomInfo.memberCount = self.roomInfo.memberCount + } + self.roomInfo = roomInfo + viewResponder?.changeRoom(title: "\(roomInfo.roomName)(\(roomInfo.roomID))") + } + + func onEnterRoomSeatListNotify(seatInfoList: [ChatSalonSeatInfo]) { + TRTCLog.out("roomLog: onSeatListChange: \(seatInfoList)") + isSeatInitSuccess = true + anchorUserIDs.removeAll() + anchorSeatList.removeAll() + var needRefreshAudience = false + var masterID = "" + seatInfoList.forEach { (item) in + let seatInfo = item + var anchorSeatInfo = ChatSalonSeatInfoModel.init { [weak self] (model) in + guard let `self` = self else { return } + self.clickSeat(model: model) + } + anchorSeatInfo.seatInfo = seatInfo + anchorSeatInfo.isOwner = roomInfo.ownerId == seatInfo.userID + if anchorSeatInfo.isOwner { + masterID = seatInfo.userID + masterAnchor = anchorSeatInfo + masterAnchor?.isUsed = true + } else { + if seatInfo.userID != "" { + TRTCLog.out("roomLog: onSeatListChange ==== : \(seatInfo.userID)") + anchorUserIDs.append(seatInfo.userID) + anchorSeatList[seatInfo.userID] = anchorSeatInfo + } + } + if memberAudienceDic.keys.contains(seatInfo.userID) { + needRefreshAudience = true + memberAudienceDic.removeValue(forKey: seatInfo.userID) + } + } + if needRefreshAudience { + viewResponder?.audienceListRefresh() + } + let seatUserIds = seatInfoList.filter({ (seat) -> Bool in + return seat.userID != "" + }).map { (seatInfo) -> String in + return seatInfo.userID + } + chatSalon.getUserInfoList(userIDList: seatUserIds) { [weak self] (code, message, userInfos) in + guard let `self` = self else { return } + guard code == 0 else { return } + var userdic: [String : ChatSalonUserInfo] = [:] + userInfos.forEach { (info) in + userdic[info.userID] = info + } + if seatInfoList.count > 0 { + if masterID != "" { + self.masterAnchor?.isUsed = true + self.masterAnchor?.seatUser = userdic[masterID] + } + } else { + return + } + for (key, value) in self.anchorSeatList { + if let info = userdic[key] { + var model = value + model.isUsed = true + model.seatUser = info + self.anchorSeatList[key] = model + } + } + self.viewResponder?.refreshAnchorInfos() + } + } + + func onAnchorEnterSeat(user: ChatSalonUserInfo) { + if user.userID == roomInfo.ownerId { + // 房主上麦就不提醒了 + if self.masterAnchor == nil { + self.masterAnchor = ChatSalonSeatInfoModel.init { [weak self] (model) in + guard let `self` = self else { return } + self.clickSeat(model: model) + } + } + self.masterAnchor?.isUsed = true + self.masterAnchor?.seatUser = user + let anchorSeatInfo = ChatSalonSeatInfo.init() + anchorSeatInfo.userID = user.userID + self.masterAnchor?.seatInfo = anchorSeatInfo + self.viewResponder?.refreshAnchorInfos() + return; + } + showNotifyMsg(messsage: "\(user.userName)\(String.enterSeatText)") + if user.userID == dependencyContainer.userID { + roomType = .anchor + } + if anchorSeatList[user.userID] == nil { + var anchorSeatInfo = ChatSalonSeatInfoModel.init { [weak self] (model) in + guard let `self` = self else { return } + self.clickSeat(model: model) + } + let seatInfo = ChatSalonSeatInfo.init() + seatInfo.mute = false + seatInfo.userID = user.userID + anchorSeatInfo.seatInfo = seatInfo + anchorSeatInfo.seatUser = user + anchorSeatInfo.isUsed = true + anchorSeatList[user.userID] = anchorSeatInfo + anchorUserIDs.append(user.userID) + self.viewResponder?.refreshAnchorInfos() + } + changeAudience(status: CSAudienceInfoModel.TYPE_IN_SEAT, user: user) + } + + func onAnchorLeaveSeat(user: ChatSalonUserInfo) { + if user.userID == roomInfo.ownerId { + // 房主下麦就不提醒了 + return; + } + if anchorSeatList[user.userID] != nil { + anchorSeatList.removeValue(forKey: user.userID) + if let index = anchorUserIDs.firstIndex(of: user.userID) { + anchorUserIDs.remove(at: index) + } + self.viewResponder?.refreshAnchorInfos() + } + showNotifyMsg(messsage: "\(user.userName)\(String.leaveSeatText)") + if user.userID == dependencyContainer.userID { + roomType = .audience + // 自己下麦,停止音效播放 + viewResponder?.stopPlayBGM() + } + changeAudience(status: CSAudienceInfoModel.TYPE_IDEL, user: user) + } + + func onSeatMute(userID: String, isMute: Bool) { + // TODO: user mute UI action. in seatInfoChange recv. + guard let seatInfo = anchorSeatList[userID] else { + return + } + if seatInfo.seatInfo?.mute != isMute { + seatInfo.seatInfo?.mute = isMute + anchorSeatList[userID] = seatInfo + viewResponder?.refreshAnchorInfos() + } + } + + func onAudienceEnter(userInfo: ChatSalonUserInfo) { + showNotifyMsg(messsage: "\(userInfo.userName)进房") + let memberEntityModel = CSAudienceInfoModel.init(type: 0, userInfo: userInfo) { [weak self] (index) in + guard let `self` = self else { return } + if index == 0 { + self.sendInvitation(userInfo: userInfo) + } else { + self.acceptTakeSeatInviattion(userInfo: userInfo) + self.viewResponder?.reuqestTakeSeatList(show: false) + } + } + if !memberAudienceDic.keys.contains(userInfo.userID) { + memberAudienceDic[userInfo.userID] = memberEntityModel + viewResponder?.audienceListRefresh() + } + + } + + func onAudienceExit(userInfo: ChatSalonUserInfo) { + memberAudienceDic.removeValue(forKey: userInfo.userID) + viewResponder?.refreshAnchorInfos() + + } + + func onUserVolumeUpdate(userVolumes: [TRTCVolumeInfo], totalVolume: Int) { + var volumeDic: [String: UInt] = [:] + userVolumes.forEach { (info) in + if let userId = info.userId { + volumeDic[userId] = info.volume + } else { + volumeDic[dependencyContainer.userID] = info.volume + } + } + var needRefreshUI = false + if let master = masterAnchor, let userId = master.seatUser?.userID { + let newIsTalking = (volumeDic[userId] ?? 0) > 25 + if master.isTalking != newIsTalking { + masterAnchor?.isTalking = newIsTalking + needRefreshUI = true + } + } + for userId in self.anchorSeatList.keys { + let isTalking = (volumeDic[userId] ?? 0) > 25 + if let orgIsTalking = self.anchorSeatList[userId]?.isTalking, orgIsTalking != isTalking { + self.anchorSeatList[userId]?.isTalking = isTalking + needRefreshUI = true + } + } + if needRefreshUI { + viewResponder?.refreshAnchorInfos() + } + } + + func onRecvRoomTextMsg(message: String, userInfo: ChatSalonUserInfo) { + let msgEntity = CSMsgEntity.init(userID: userInfo.userID, + userName: userInfo.userName, + content: message, + invitedId: "", + type: CSMsgEntity.TYPE_NORMAL) + notifyMsg(entity: msgEntity) + } + + func onRecvRoomCustomMsg(cmd: String, message: String, userInfo: ChatSalonUserInfo) { + + } + + func onReceiveNewInvitation(identifier: String, inviter: String, cmd: String, content: String) { + TRTCLog.out("receive message: \(cmd) : \(content)") + if roomType == .audience { + if cmd == ChatSalonConstants.CMD_PICK_UP_SEAT { + recvPickSeat(identifier: identifier, cmd: cmd, content: content) + } + } + if roomType == .anchor && roomInfo.ownerId == dependencyContainer.userID { + if cmd == ChatSalonConstants.CMD_REQUEST_TAKE_SEAT { + recvTakeSeat(identifier: identifier, inviter: inviter, content: content) + } + } + } + + func onInviteeAccepted(identifier: String, invitee: String) { + if roomType == .audience { + guard let seatIndex = mInvitationSeatDic.removeValue(forKey: identifier) else { + return + } + if anchorSeatList[dependencyContainer.userID] != nil { + // 已经在麦上了 + return + } + viewResponder?.showHandUpTips(isShow: false) + chatSalon.enterSeat { [weak self] (code, message) in + guard let `self` = self else { return } + if code == 0 { + self.viewResponder?.showToast(message: .enterRoomSuccText) + } else { + self.viewResponder?.showToast(message: .enterSeatFailedText) + } + } + } + } + + func onInviteeRejected(identifier: String, invitee: String) { + if let seatInvitation = mPickCSSeatInvitationDic.removeValue(forKey: identifier) { + guard let audience = memberAudienceDic[seatInvitation.inviteUserId] else { return } + changeAudience(status: CSAudienceInfoModel.TYPE_IDEL, user: audience.userInfo) + } + } + + func onInvitationCancelled(identifier: String, invitee: String) { + + } + + func onAudioAvailable(userID: String, available: Bool) { + + } +} + +fileprivate extension String { + static let closedMicText = ChatSalonLocalized.getLocalizedString(key: "Mic.Muted") + static let openedMicText = ChatSalonLocalized.getLocalizedString(key: "Mic.Unmuted") + static let micInitNotReadyText = ChatSalonLocalized.getLocalizedString(key: "The seat list is not yet initialized!") + static let enterRoomSuccText = ChatSalonLocalized.getLocalizedString(key: "Enter room success") + static let enterRoomFailText = ChatSalonLocalized.getLocalizedString(key: "Enter room failed") + static let createRoomFailedText = ChatSalonLocalized.getLocalizedString(key: "failed to create a room") + static let alreadyIsAnchorText = ChatSalonLocalized.getLocalizedString(key: "you are a speaker") + static let roomNotReadyText = ChatSalonLocalized.getLocalizedString(key: "The room is loading") + static let waitHostAcceptText = ChatSalonLocalized.getLocalizedString(key: "waiting for host's consent") + static let takeSeatSendFailed = ChatSalonLocalized.getLocalizedString(key: "failed to sent the hand-up message") + static let masterOnSeatSuccess = ChatSalonLocalized.getLocalizedString(key: "Host succeeded in occupying the seat") + static let masterOnSeatFailed = ChatSalonLocalized.getLocalizedString(key: "Host failed to occupy the seat") + static let onlyAnchorUse = ChatSalonLocalized.getLocalizedString(key: "Only the host can operate") + static let kickOutMicText = ChatSalonLocalized.getLocalizedString(key: "Action.move to the audience") + static let inviatttionTimeoutText = ChatSalonLocalized.getLocalizedString(key: "The request has expired") + static let acceptInvitationFailed = ChatSalonLocalized.getLocalizedString(key: "Failed to accept request") + static let leaveSeatSuccText = ChatSalonLocalized.getLocalizedString(key: "succeeded in becoming an audience") + static let leaveSeatFailedText = ChatSalonLocalized.getLocalizedString(key: "failed to become an audience") + static let hostDestroyRoomText = ChatSalonLocalized.getLocalizedString(key: "The host has closed the room") + static let enterSeatText = ChatSalonLocalized.getLocalizedString(key: "Hands up") + static let leaveSeatText = ChatSalonLocalized.getLocalizedString(key: "Message.move to the audience") + static let enterSeatSuccessText = ChatSalonLocalized.getLocalizedString(key: "succeeded in becoming a speaker") + static let enterSeatFailedText = ChatSalonLocalized.getLocalizedString(key: "failed to become a speaker") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonRootView.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonRootView.swift new file mode 100644 index 00000000..0de600c0 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonRootView.swift @@ -0,0 +1,290 @@ +// +// TRTCCreateChatSalonRootView.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/4. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit +import SnapKit +import Toast_Swift + +class TRTCCreateChatSalonRootView: UIView { + static let viewTitle: String = .titleText + private var isViewReady: Bool = false + private let viewModel: TRTCCreateChatSalonViewModel + + weak var rootViewController: UIViewController? + + required init?(coder: NSCoder) { + fatalError("init corder is not permit in this view") + } + + init(viewModel: TRTCCreateChatSalonViewModel, frame: CGRect = .zero) { + self.viewModel = viewModel + super.init(frame: frame) + roomNameInputTextFiled.text = viewModel.roomName + userNameTextFiled.text = viewModel.userName + bindInteraction() + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + let backgroundLayer: CALayer = { + // fillCode + let layer = CAGradientLayer() + layer.colors = [UIColor.init(0x13294b).cgColor, UIColor.init(0x000000).cgColor] + layer.locations = [0.2, 1.0] + layer.startPoint = CGPoint(x: 0.4, y: 0) + layer.endPoint = CGPoint(x: 0.6, y: 1.0) + return layer + }() + + // 输入框 + let inputContainer: UIView = { + let view = UIView.init(frame: .zero) + // fillCode + let layer = CAGradientLayer() + layer.colors = [UIColor(red: 0.05, green: 0.17, blue: 0.36, alpha: 1).cgColor, UIColor(red: 0.07, green: 0.15, blue: 0.33, alpha: 1).cgColor] + layer.locations = [0, 1] + layer.frame = CGRect.init(origin: .zero, size: .init(width: UIScreen.main.bounds.width - 40, height: 113)) + layer.startPoint = CGPoint(x: 0.26, y: 0.13) + layer.endPoint = CGPoint(x: 0.92, y: 0.92) + view.layer.addSublayer(layer) + return view + }() + + let roomNumberLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = .topicText + label.font = UIFont.systemFont(ofSize: 16.0) + label.textColor = UIColor.init(0xEBF4FF) + label.textAlignment = .left + label.adjustsFontSizeToFitWidth = true + return label + }() + + let roomNameInputTextFiled: UITextField = { + let textField = UITextField.init(frame: .zero) + textField.attributedPlaceholder = NSAttributedString.init(string: .topicPlaceholdText, attributes: [.font: UIFont.systemFont(ofSize: 16.0), .foregroundColor: UIColor.placeholderBackColor]) + textField.textColor = UIColor.init(0xEBF4FF) + textField.font = UIFont.systemFont(ofSize: 16.0) + return textField + }() + + + let cuttingLine: UIView = { + let view = UIView.init(frame: .zero) + view.backgroundColor = UIColor.init(0xFFFFFF, alpha: 0.11) + return view + }() + + let userNameLabel: UILabel = { + let label = UILabel.init(frame: .zero) + label.text = .userNameText + label.font = UIFont.systemFont(ofSize: 16.0) + label.textColor = UIColor.init(0xEBF4FF) + label.textAlignment = .left + label.adjustsFontSizeToFitWidth = true + return label + }() + + let userNameTextFiled: UITextField = { + let textField = UITextField.init(frame: .zero) + textField.attributedPlaceholder = NSAttributedString.init(string: .userNamePlaceholdText, attributes: [.font: UIFont.systemFont(ofSize: 16.0), .foregroundColor: UIColor.placeholderBackColor]) + textField.textColor = UIColor.init(0xEBF4FF) + textField.font = UIFont.systemFont(ofSize: 16.0) + return textField + }() + + let enterRoomButton: UIButton = { + let button = UIButton.init(type: .custom) + button.titleLabel?.font = UIFont.systemFont(ofSize: 16.0) + button.setTitleColor(UIColor.init(0x56749E), for: .disabled) + button.setTitleColor(UIColor.init(0xFFFFFF), for: .normal) + button.setTitle(.startButtonText, for: .normal) + button.setBackgroundImage(UIColor.inputImageBackColor.trans2Image(), for: .disabled) + button.setBackgroundImage(UIColor.buttonBackColor.trans2Image(), for: .normal) + return button + }() + +// let tipsLabel: UILabel = { +// let label = UILabel.init(frame: .zero) +// label.text = "若房间号不存在将自动创建并加入该房间" +// label.font = UIFont.systemFont(ofSize: 16.0) +// label.textColor = .placeholderBackColor +// label.textAlignment = .center +// label.adjustsFontSizeToFitWidth = true +// return label +// }() + + // MARK: - 视图生命周期 + override func didMoveToWindow() { + super.didMoveToWindow() + guard !isViewReady else { + return + } + isViewReady = true + constructViewHierarchy() // 视图层级布局 + activateConstraints() // 生成约束(此时有可能拿不到父视图正确的frame) + } + + func constructViewHierarchy() { + /// 此方法内只做add子视图操作 + backgroundLayer.frame = self.bounds; + layer.insertSublayer(backgroundLayer, at: 0) + // 输入区域 + addSubview(inputContainer) + inputContainer.addSubview(roomNumberLabel) + inputContainer.addSubview(roomNameInputTextFiled) + inputContainer.addSubview(cuttingLine) + inputContainer.addSubview(userNameLabel) + inputContainer.addSubview(userNameTextFiled) + // 进入按钮区域 + addSubview(enterRoomButton) +// addSubview(tipsLabel) + } + + func activateConstraints() { + activateConstraintsOfInput() + activateConstraintsOfEnterRoom() + } + + func bindInteraction() { + roomNameInputTextFiled.delegate = self + userNameTextFiled.delegate = self + + roomNameInputTextFiled.text = viewModel.roomName + userNameTextFiled.text = viewModel.userName + enterRoomButton.addTarget(self, action: #selector(enterRoomAction(_:)), for: .touchUpInside) + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + super.touchesBegan(touches, with: event) + self.endEditing(true) + } +} + +extension TRTCCreateChatSalonRootView: UITextFieldDelegate { + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + if textField == roomNameInputTextFiled { + // 限制只能输入数字 + return true + } else if textField == userNameTextFiled { + // 可以对输入做限制 + return true + } + return true + } + + func textFieldDidEndEditing(_ textField: UITextField) { + if textField == roomNameInputTextFiled { + viewModel.roomName = textField.text ?? "" + } else { + viewModel.userName = textField.text ?? "" + } + } +} + +extension TRTCCreateChatSalonRootView { + + @objc + func enterRoomAction(_ sender: UIButton) { + // 获取输入 + guard let roomNameString = roomNameInputTextFiled.text, let userNameString = userNameTextFiled.text else { + return + } + guard roomNameString != "" && userNameString != "" else { + makeToast(String.nameEmptyToast) + return + } + viewModel.roomName = roomNameString + viewModel.userName = userNameString + viewModel.createRoom() + } +} + +extension TRTCCreateChatSalonRootView: TRTCCreateChatSalonViewResponder { + func push(viewController: UIViewController) { + rootViewController?.navigationController?.pushViewController(viewController, animated: true) + } +} + +// MARK: - 自动化约束 +extension TRTCCreateChatSalonRootView { + func activateConstraintsOfInput() { + inputContainer.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(20) + make.right.equalToSuperview().offset(-20) + if #available(iOS 11.0, *) { + make.top.equalTo(safeAreaLayoutGuide.snp.top).offset(15) + } else { + make.top.equalToSuperview().offset(15) + } + make.height.equalTo(113) + } + cuttingLine.snp.makeConstraints { (make) in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(16) + make.right.equalToSuperview().offset(-16) + make.height.equalTo(0.5) + } + roomNumberLabel.snp.makeConstraints { (make) in + make.top.equalToSuperview() + make.bottom.equalTo(cuttingLine.snp.top) + make.left.equalTo(cuttingLine.snp.left) + make.width.equalTo(55) + } + roomNameInputTextFiled.snp.makeConstraints { (make) in + make.right.equalTo(cuttingLine.snp.right) + make.top.equalToSuperview() + make.bottom.equalTo(cuttingLine.snp.top) + make.left.equalTo(roomNumberLabel.snp.right).offset(30) + } + userNameLabel.snp.makeConstraints { (make) in + make.bottom.equalToSuperview() + make.top.equalTo(cuttingLine.snp.bottom) + make.left.equalTo(cuttingLine.snp.left) + make.width.equalTo(55) + } + userNameTextFiled.snp.makeConstraints { (make) in + make.right.equalTo(cuttingLine.snp.right) + make.bottom.equalToSuperview() + make.top.equalTo(cuttingLine.snp.bottom) + make.left.equalTo(userNameLabel.snp.right).offset(30) + } + } + + func activateConstraintsOfEnterRoom() { + enterRoomButton.snp.makeConstraints { (make) in + make.left.equalToSuperview().offset(20) + make.right.equalToSuperview().offset(-20) + make.height.equalTo(48) + make.top.equalTo(userNameTextFiled.snp.bottom).offset(30) + } + +// tipsLabel.snp.makeConstraints { (make) in +// make.centerX.equalToSuperview() +// make.top.equalTo(enterRoomButton.snp.bottom).offset(30) +// make.left.right.equalTo(enterRoomButton) +// } + } +} + +fileprivate extension String { + static let titleText = ChatSalonLocalized.getLocalizedString(key: "create a chat salon room") + static let topicText = ChatSalonLocalized.getLocalizedString(key: "topic") + static let topicPlaceholdText = ChatSalonLocalized.getLocalizedString(key: "default room topic") + static let userNameText = ChatSalonLocalized.getLocalizedString(key: "user ID") + static let userNamePlaceholdText = ChatSalonLocalized.getLocalizedString(key: "default user ID") + static let startButtonText = ChatSalonLocalized.getLocalizedString(key: "Let’s go") + static let nameEmptyToast = ChatSalonLocalized.getLocalizedString(key: "Nickname or username is empty") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewController.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewController.swift new file mode 100644 index 00000000..19b14c5d --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewController.swift @@ -0,0 +1,47 @@ +// +// TRTCCreateChatSalonViewController.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/4. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +class TRTCCreateChatSalonViewController: UIViewController { + // 依赖管理者 + let dependencyContainer: TRTCChatSalonEnteryControl + + init(dependencyContainer: TRTCChatSalonEnteryControl) { + self.dependencyContainer = dependencyContainer + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + override func viewDidLoad() { + super.viewDidLoad() + title = TRTCCreateChatSalonRootView.viewTitle + let backItem = UIBarButtonItem.init(image: UIImage.init(named: "navigationbar_back"), style: .plain, target: self, action: #selector(cancel)) + self.navigationItem.leftBarButtonItem = backItem + } + + override func loadView() { + let chatSalonModel = dependencyContainer.makeCreateChatSalonViewModel() + let rootView = TRTCCreateChatSalonRootView.init(viewModel: chatSalonModel) + chatSalonModel.viewResponder = rootView + rootView.rootViewController = self + view = rootView + } + + /// 取消 + @objc func cancel() { + navigationController?.popViewController(animated: true) + } +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewModel.swift b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewModel.swift new file mode 100644 index 00000000..420b0ade --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/TRTCCreateChatSalonViewController/TRTCCreateChatSalonViewModel.swift @@ -0,0 +1,76 @@ +// +// TRTCCreateChatSalonViewModel.swift +// TRTCChatSalonDemo +// +// Created by abyyxwang on 2020/6/8. +// Copyright © 2020 tencent. All rights reserved. +// + +import UIKit + +enum ChatSalonRole { + case anchor // 主播 + case audience // 观众 +} + +enum ChatSalonToneQuality: Int { + case speech = 1 + case defaultQuality + case music +} + +protocol TRTCCreateChatSalonViewResponder: class { + func push(viewController: UIViewController) +} + +class TRTCCreateChatSalonViewModel { + private let dependencyContainer: TRTCChatSalonEnteryControl + + public weak var viewResponder: TRTCCreateChatSalonViewResponder? + + var chatSalon: TRTCChatSalon { + return dependencyContainer.getChatSalon() + } + + var roomName: String = "" + var userName: String = "" + var needRequest: Bool = true + var toneQuality: ChatSalonToneQuality = .music + + /// 初始化方法 + /// - Parameter container: 依赖管理容器,负责ChatSalon模块的依赖管理 + init(container: TRTCChatSalonEnteryControl) { + self.dependencyContainer = container + let name = ProfileManager.shared.curUserModel?.name ?? dependencyContainer.userID + roomName = "\(name)"+String.salonRoomNameSuffix + userName = name + } + + deinit { + TRTCLog.out("deinit \(type(of: self))") + } + + func createRoom() { + let userID = ProfileManager.shared.curUserID() ?? dependencyContainer.userID + let coverAvatar = ProfileManager.shared.curUserModel?.avatar ?? "" + let roomId = getRoomId() + let roomInfo = ChatSalonInfo.init(roomID: roomId, ownerId: userID, memberCount: 7) + roomInfo.ownerName = userName + roomInfo.coverUrl = coverAvatar + roomInfo.roomName = roomName + roomInfo.needRequest = needRequest + let vc = self.dependencyContainer.makeChatSalonViewController(roomInfo:roomInfo, role: .anchor, toneQuality: self.toneQuality) + viewResponder?.push(viewController: vc) + } + + func getRoomId() -> Int { + let userID = ProfileManager.shared.curUserID() ?? dependencyContainer.userID + let result = "\(userID)_voice_room".hash & 0x7FFFFFFF + TRTCLog.out("hashValue:room id:\(result), userID: \(userID)") + return result + } +} + +fileprivate extension String { + static let salonRoomNameSuffix = ChatSalonLocalized.getLocalizedString(key: "'s salon room") +} diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/en.lproj/TRTCChatSalonDemoLocalized.strings b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/en.lproj/TRTCChatSalonDemoLocalized.strings new file mode 100644 index 00000000..fbdbd861 --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/en.lproj/TRTCChatSalonDemoLocalized.strings @@ -0,0 +1,66 @@ +/* + TRTCChatSalonDemo.strings + TXLiteAVDemo + + Created by abyyxwang on 2021/3/3. + Copyright © 2021 Tencent. All rights reserved. +*/ +"'s salon room" = "'s salon room"; +"create a chat salon room" = "create a chat salon room"; +"topic" = "topic"; +"default room topic" = "default room topic"; +"user ID" = "user ID"; +"default user ID" = "default user ID"; +"Let’s go" = "Let’s go"; +"Nickname or username is empty" = "Nickname or username is empty"; +"Accept" = "Accept"; +"Raised hands" = "Raised hands"; +"Close" = "Close"; +"Welcome" = "Welcome"; +"Dismiss" = "Dismiss"; +"applies to become a speaker" = "applies to become a speaker"; +"You raised your hand! We'll let the speakers know you want to talk~" = "You raised your hand! We'll let the speakers know you want to talk~"; +"room ID" = "room ID"; +"You want to leave the room?" = "You want to leave the room?"; +"Audience.Confirm" = "Confirm"; +"Wait a bit" = "Wait a bit"; +"Seat.Muted" = "Muted"; +"Seat.Unmuted" = "Unmuted"; +"The seat list is not yet initialized!" = "The seat list is not yet initialized!"; +"Enter room success" = "Enter room success"; +"Enter room failed" = "Enter room failed"; +"failed to create a room" = "failed to create a room"; +"you are a speaker" = "you are a speaker"; +"The room is loading" = "The room is loading"; +"waiting for host's consent" = "waiting for host's consent"; +"failed to sent the hand-up message" = "failed to sent the hand-up message"; +"Host succeeded in occupying the seat" = "Host succeeded in occupying the seat"; +"Host failed to occupy the seat" = "Host failed to occupy the seat"; +"Only the host can operate" = "Only the host can operate"; +"Action.move to the audience" = "move to the audience"; +"The request has expired" = "The request has expired"; +"Failed to accept request" = "Failed to accept request"; +"succeeded in becoming an audience" = "succeeded in becoming an audience"; +"failed to become an audience" = "failed to become an audience"; +"The host has closed the room" = "The host has closed the room"; +"Hands up" = "Hands up"; +"Message.move to the audience" = "move to the audience"; +"succeeded in becoming a speaker" = "succeeded in becoming a speaker"; +"failed to become a speaker" = "failed to become a speaker"; +"speakers" = "speakers"; +"audiences" = "audiences"; +"Leave quietly" = "Leave quietly"; +"Owner.Confirm" = "Confirm"; +"Cancel" = "Cancel"; +"you want to end the room?" = "you want to end the room?"; +"Mic.Muted" = "Muted"; +"Mic.Unmuted" = "Unmuted"; +"Please select" = "Please select"; +"chat salon" = "chat salon"; +"online" = "online"; +"pull down to refresh" = "pull down to refresh"; +"loading…" = "loading…"; +"invalid appid" = "invalid appid"; +"No content yet~" = "No content yet~"; +"Failed to get room list" = "Failed to get room list"; +"Failed to get list" = "Failed to get list"; diff --git a/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/zh-Hans.lproj/TRTCChatSalonDemoLocalized.strings b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/zh-Hans.lproj/TRTCChatSalonDemoLocalized.strings new file mode 100644 index 00000000..2d42b24f --- /dev/null +++ b/Demo/TXLiteAVDemo/TRTCChatSalonDemo/ui/zh-Hans.lproj/TRTCChatSalonDemoLocalized.strings @@ -0,0 +1,66 @@ +/* + TRTCChatSalonDemo.strings + TXLiteAVDemo + + Created by abyyxwang on 2021/3/3. + Copyright © 2021 Tencent. All rights reserved. +*/ +"'s salon room" = " 的沙龙"; +"create a chat salon room" = "创建语音沙龙"; +"topic" = "主题"; +"default room topic" = "默认房间名称"; +"user ID" = "用户名"; +"default user ID" = "默认用户名"; +"Let’s go" = "开始交谈"; +"Nickname or username is empty" = "昵称或用户名为空"; +"Accept" = "接受"; +"Raised hands" = "举手列表"; +"Close" = "关闭"; +"Welcome" = "欢迎"; +"Dismiss" = "忽略"; +"applies to become a speaker" = "申请成为主播"; +"You raised your hand! We'll let the speakers know you want to talk~" = "举手成功!等待管理员通过~"; +"room ID" = "房间号"; +"You want to leave the room?" = "确认离开房间吗"; +"Audience.Confirm" = "确认"; +"Wait a bit" = "再等等"; +"Mic.Muted" = "已关闭麦克风"; +"Mic.Unmuted" = "已打开麦克风"; +"The seat list is not yet initialized!" = "麦位列表还未初始化哦!"; +"Enter room success" = "进房成功"; +"Enter room failed" = "进房失败"; +"failed to create a room" = "创建房间失败"; +"you are a speaker" = "已经是上麦主播了"; +"The room is loading" = "房间还没有准备好"; +"waiting for host's consent" = "正在等待房主同意"; +"failed to sent the hand-up message" = "举手信息发送失败:"; +"Host succeeded in occupying the seat" = "房主占座成功"; +"Host failed to occupy the seat" = "房主占座失败"; +"Only the host can operate" = "只有主播才能操作"; +"Action.move to the audience" = "要求下麦"; +"The request has expired" = "该请求已过期"; +"Failed to accept request" = "接受请求失败"; +"succeeded in becoming an audience" = "下麦成功"; +"failed to become an audience" = "下麦失败:"; +"The host has closed the room" = "房主已解散房间"; +"Hands up" = "上麦"; +"Message.move to the audience" = "下麦"; +"succeeded in becoming a speaker" = "上麦成功"; +"failed to become a speaker" = "上麦失败"; +"speakers" = "主播"; +"audiences" = "听众"; +"Leave quietly" = "安静离开~"; +"Owner.Confirm" = "确定"; +"Cancel" = "取消"; +"you want to end the room?" = "离开会解散房间,确定离开吗?"; +"Seat.Muted" = "被房主禁言"; +"Seat.Unmuted" = "被房主解禁"; +"Please select" = "请选择"; +"chat salon" = "语音沙龙"; +"online" = "在线"; +"pull down to refresh" = "下拉刷新"; +"loading…" = "刷新中"; +"invalid appid" = "APPID 不正确"; +"No content yet~" = "当前暂无内容哦~"; +"Failed to get room list" = "获取房间列表失败"; +"Failed to get list" = "获取列表失败"; diff --git a/Demo/TXLiteAVDemo/TRTCLiveRoomDemo/ui/Anchor/TCAnchorToolbarView.m b/Demo/TXLiteAVDemo/TRTCLiveRoomDemo/ui/Anchor/TCAnchorToolbarView.m index 45eaf01f..350aed25 100644 --- a/Demo/TXLiteAVDemo/TRTCLiveRoomDemo/ui/Anchor/TCAnchorToolbarView.m +++ b/Demo/TXLiteAVDemo/TRTCLiveRoomDemo/ui/Anchor/TCAnchorToolbarView.m @@ -18,7 +18,7 @@ #import "UIColor+MLPFlatColors.h" #import "TXLiteAVDemo-Swift.h" -@interface TCAnchorToolbarView () +@interface TCAnchorToolbarView () @property(strong, nonatomic)TCShowLiveTopView *topView; @@ -325,6 +325,7 @@ - (void)initUI { //******************** // 音乐 _vMusicPanel = [[AudioEffectSettingView alloc] initWithType:AudioEffectSettingViewCustom]; + _vMusicPanel.delegate = self; //*** //BGM _vBGMPanel = [[UIView alloc] init]; @@ -1013,6 +1014,12 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField{ return YES; } +- (void)onEffectViewHidden:(BOOL)isHidden { + if (isHidden) { + [self addGestureRecognizer:_tap]; + } +} + #pragma mark - 滑动隐藏界面UI - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { @@ -1042,7 +1049,6 @@ - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if (!_vMusicPanel.isHidden && !_isTouchMusicPanel) { [_vMusicPanel hide]; - [self addGestureRecognizer:_tap]; } } diff --git a/Demo/TXLiteAVDemo/TRTCVoiceRoomDemo/ui/TRTCVoiceRoomViewController/TRTCVoiceRoomViewModel.swift b/Demo/TXLiteAVDemo/TRTCVoiceRoomDemo/ui/TRTCVoiceRoomViewController/TRTCVoiceRoomViewModel.swift index 29bc0880..ba6488a9 100644 --- a/Demo/TXLiteAVDemo/TRTCVoiceRoomDemo/ui/TRTCVoiceRoomViewController/TRTCVoiceRoomViewModel.swift +++ b/Demo/TXLiteAVDemo/TRTCVoiceRoomDemo/ui/TRTCVoiceRoomViewController/TRTCVoiceRoomViewModel.swift @@ -129,12 +129,10 @@ class TRTCVoiceRoomViewModel: NSObject { return false } isSelfMute = isMute + voiceRoom.muteLocalAudio(mute: isMute) if isMute { - voiceRoom.stopMicrophone() - viewResponder?.stopPlayBGM() viewResponder?.showToast(message: "已关闭麦克风") } else { - voiceRoom.startMicrophone() viewResponder?.recoveryVoiceSetting() viewResponder?.showToast(message: "已打开麦克风") } diff --git a/Demo/TXLiteAVDemo/UGCKit/UGCKit/UGCKit.xcodeproj/project.pbxproj b/Demo/TXLiteAVDemo/UGCKit/UGCKit/UGCKit.xcodeproj/project.pbxproj index 41beb67e..9e3b4db2 100644 --- a/Demo/TXLiteAVDemo/UGCKit/UGCKit/UGCKit.xcodeproj/project.pbxproj +++ b/Demo/TXLiteAVDemo/UGCKit/UGCKit/UGCKit.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 3A4E0AD7B8D94EEE9C50DA9D /* TXLiteAVSDK_UGC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0278B72F0AA5FD97FEB7C80A /* TXLiteAVSDK_UGC.framework */; }; 40DD579A247383E200C72F27 /* TXLiteAVSDK_Enterprise.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40A49D7F24598E3200BFCB18 /* TXLiteAVSDK_Enterprise.framework */; }; 40F4D69D2474CA2100847F5B /* TCBeautyPanel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 40F4D69C2474CA2100847F5B /* TCBeautyPanel.framework */; }; 4500A6D12382793300147B05 /* UGCKitMediaPicker.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 453DE2F6237945DC0083E759 /* UGCKitMediaPicker.storyboard */; }; @@ -131,11 +132,11 @@ 45E8294E2384ED1200702418 /* UGCKitAudioEffectPanel.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E8294C2384ED1200702418 /* UGCKitAudioEffectPanel.h */; }; 45E8294F2384ED1200702418 /* UGCKitAudioEffectPanel.m in Sources */ = {isa = PBXBuildFile; fileRef = 45E8294D2384ED1200702418 /* UGCKitAudioEffectPanel.m */; }; 45E907AB239E253000CEC8F1 /* TXLiteAVSDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 45E90782239E253000CEC8F1 /* TXLiteAVSDK.h */; }; - E08BC83B63D90EC6FA4F6CC0 /* TXLiteAVSDK_UGC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6986F6C459B27C3DB6A70057 /* TXLiteAVSDK_UGC.framework */; }; F2DA415A23917DA200EB0AAB /* UGCKitBGMCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 45D52F12238D231A006F71FA /* UGCKitBGMCell.xib */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0278B72F0AA5FD97FEB7C80A /* TXLiteAVSDK_UGC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXLiteAVSDK_UGC.framework; path = ../../../../SDK/TXLiteAVSDK_UGC.framework; sourceTree = ""; }; 40A49D7F24598E3200BFCB18 /* TXLiteAVSDK_Enterprise.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXLiteAVSDK_Enterprise.framework; path = ../../../../SDK/TXLiteAVSDK_Professional.framework; sourceTree = ""; }; 40F4D69C2474CA2100847F5B /* TCBeautyPanel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = TCBeautyPanel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4507F44C23AB707600804AD5 /* UGCKitPieProgressView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UGCKitPieProgressView.h; sourceTree = ""; }; @@ -276,7 +277,6 @@ 45E8294D2384ED1200702418 /* UGCKitAudioEffectPanel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UGCKitAudioEffectPanel.m; sourceTree = ""; }; 45E90782239E253000CEC8F1 /* TXLiteAVSDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXLiteAVSDK.h; sourceTree = ""; }; 45E9FFC52399FEAD00CEC8F1 /* UGCKitLocalization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UGCKitLocalization.h; sourceTree = ""; }; - 6986F6C459B27C3DB6A70057 /* TXLiteAVSDK_UGC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = TXLiteAVSDK_UGC.framework; path = ../../../../SDK/TXLiteAVSDK_UGC.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -288,7 +288,7 @@ 40DD579A247383E200C72F27 /* TXLiteAVSDK_Enterprise.framework in Frameworks */, 453DE40C23794ECD0083E759 /* AssetsLibrary.framework in Frameworks */, 453DE40A23794E900083E759 /* OpenAL.framework in Frameworks */, - E08BC83B63D90EC6FA4F6CC0 /* TXLiteAVSDK_UGC.framework in Frameworks */, + 3A4E0AD7B8D94EEE9C50DA9D /* TXLiteAVSDK_UGC.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -577,7 +577,7 @@ 453DE40723794E8A0083E759 /* libresolv.tbd */, 453DE40523794E800083E759 /* libsqlite3.tbd */, 453DE40323794E020083E759 /* libc++.tbd */, - 6986F6C459B27C3DB6A70057 /* TXLiteAVSDK_UGC.framework */, + 0278B72F0AA5FD97FEB7C80A /* TXLiteAVSDK_UGC.framework */, ); name = Frameworks; sourceTree = ""; diff --git a/Demo/TXLiteAVDemo/UGCVideoUploadDemo/VideoUpload/TVCClientInner.h b/Demo/TXLiteAVDemo/UGCVideoUploadDemo/VideoUpload/TVCClientInner.h index a6cc3eee..c251d418 100644 --- a/Demo/TXLiteAVDemo/UGCVideoUploadDemo/VideoUpload/TVCClientInner.h +++ b/Demo/TXLiteAVDemo/UGCVideoUploadDemo/VideoUpload/TVCClientInner.h @@ -21,7 +21,7 @@ #define kMessage @"message" #define kData @"data" -#define TVCVersion @"8.4.9944" +#define TVCVersion @"8.5.10018" #pragma mark - COS config //字段废弃,作为InitUploadUGC的占位字段