|
@@ -1,2491 +0,0 @@
|
|
|
-//
|
|
|
-// LiveVideoRoomViewController.m
|
|
|
-// KulexiuForTeacher
|
|
|
-//
|
|
|
-// Created by Kyle on 2022/3/30.
|
|
|
-//
|
|
|
-
|
|
|
-#import "LiveVideoRoomViewController.h"
|
|
|
-#import "KSChatInputBarControl.h"
|
|
|
-#import "LiveRoomHeadView.h"
|
|
|
-#import "LiveRoomBottomView.h"
|
|
|
-#import "KSRCMessageModel.h"
|
|
|
-#import "UserInfoManager.h"
|
|
|
-#import "KSChatroomMessageCenter.h"
|
|
|
-#import <RongIMKit/RongIMKit.h>
|
|
|
-#import "KSChatroomTextCell.h"
|
|
|
-
|
|
|
-#import "KSLiveStreamVideo.h"
|
|
|
-#import "SeatContentView.h"
|
|
|
-#import "LiveroomTimeManager.h"
|
|
|
-#import "KSLiveEmptyView.h"
|
|
|
-#import "KSChatVideoView.h"
|
|
|
-#import "LiveRoomLikeLayer.h"
|
|
|
-#import "KSDragWindowManager.h"
|
|
|
-
|
|
|
-#import "KSLiveBadNetView.h"
|
|
|
-#import <Lottie/Lottie.h>
|
|
|
-#import "KSShopCardView.h"
|
|
|
-#import "KSLiveWebViewController.h"
|
|
|
-
|
|
|
-#import "KSLiveEndView.h"
|
|
|
-#import "LiveAnimationView.h"
|
|
|
-
|
|
|
-#import "LiveRoomAlertView.h"
|
|
|
-#import "LiveApplyView.h"
|
|
|
-#import "LiveApplyingView.h"
|
|
|
-#import "ShareLiveDisplayView.h"
|
|
|
-
|
|
|
-
|
|
|
-#import "UIImage+KSScreenShot.h"
|
|
|
-#import "TZImageManager.h"
|
|
|
-#import "RecordCheckManager.h"
|
|
|
-#import "KSPremissionAlert.h"
|
|
|
-#import "KSUMShareManager.h"
|
|
|
-
|
|
|
-#define AUTOHIDE_TIME (10.0f)
|
|
|
-
|
|
|
-#define PACKAGE_LOST (0.30f)
|
|
|
-typedef NS_ENUM(NSInteger, MICSTATUS) {
|
|
|
- MICSTATUS_NOMAL, // 正常状态
|
|
|
- MICSTATUS_WAITING, // 申请中
|
|
|
- MICSTATUS_CONNECTING, // 连麦中
|
|
|
-};
|
|
|
-
|
|
|
-@interface LiveVideoRoomViewController ()<RCRTCEngineEventDelegate,RCRTCRoomEventDelegate,RCRTCStatusReportDelegate,UIGestureRecognizerDelegate,KSChatInputBarControlDelegate,UITableViewDataSource,UITableViewDelegate,LiveroomTimeManagerDelegate>
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveroomTimeManager *timeManager;
|
|
|
-// 音频配置
|
|
|
-@property(strong, nonatomic) RCRTCEngine *engine;
|
|
|
-
|
|
|
-@property (nonatomic, strong) RCRTCRoom *room;
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSLiveStreamVideo *localVideo;
|
|
|
-
|
|
|
-@property (nonatomic) NSMutableArray <KSLiveStreamVideo *>*streamVideos;
|
|
|
-
|
|
|
-// 视频主窗口容器
|
|
|
-@property (nonatomic, strong) UIView *videoContainerView;
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSChatVideoView *videoView;
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveRoomHeadView *headView;
|
|
|
-
|
|
|
-@property (nonatomic, copy) LiveRoomBottomView *bottomView;
|
|
|
-/**
|
|
|
- 上次点赞按钮点击时间
|
|
|
- */
|
|
|
-@property(nonatomic, assign) NSTimeInterval lastClickPraiseTime;
|
|
|
-// 连麦状态
|
|
|
-@property (nonatomic, assign) MICSTATUS micStatus;
|
|
|
-/// 提示窗
|
|
|
-@property (nonatomic, strong) LiveRoomAlertView *alertView;
|
|
|
-/// 连麦的视图
|
|
|
-@property (nonatomic, strong) SeatContentView *seatContainer;
|
|
|
-// 聊天UI
|
|
|
-/*!
|
|
|
- 消息列表CollectionView和输入框都在这个view里
|
|
|
- */
|
|
|
-@property(nonatomic, strong) UIView *messageContentView;
|
|
|
-
|
|
|
-/*!
|
|
|
- 会话页面的TableView
|
|
|
- */
|
|
|
-@property (nonatomic, strong) UITableView *conversationMessageTableView;
|
|
|
-
|
|
|
-/**
|
|
|
- 输入工具栏
|
|
|
- */
|
|
|
-@property(nonatomic,strong) KSChatInputBarControl *inputBar;
|
|
|
-/**
|
|
|
- * 是否需要滚动到底部
|
|
|
- */
|
|
|
-@property(nonatomic, assign) BOOL isNeedScrollToButtom;
|
|
|
-
|
|
|
-/*!
|
|
|
- 聊天内容的消息Cell数据模型的数据源
|
|
|
-
|
|
|
- @discussion 数据源中存放的元素为消息Cell的数据模型,即RCDLiveMessageModel对象。
|
|
|
- */
|
|
|
-@property(nonatomic, strong) NSMutableArray<KSRCMessageModel *> *conversationDataRepository;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isImConnected;
|
|
|
-
|
|
|
-/// 老师是否在房间
|
|
|
-@property (nonatomic, assign) BOOL isCreaterInRoom;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isCreaterVideoEnable;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isCreaterAudioEnable;
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSLiveEmptyView *emptyView;
|
|
|
-
|
|
|
-/// 是否在切换身份
|
|
|
-@property (nonatomic, assign) BOOL isTransferRole;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL hasSendWelcomeMessage;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL hasShowSuspendView;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isPackageLostTips;
|
|
|
-
|
|
|
-@property (nonatomic, assign) NSTimeInterval lostStartTime; // 开始丢包事件
|
|
|
-
|
|
|
-@property (nonatomic, assign) NSTimeInterval bitErrorTime; // video bit zero start
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSLiveBadNetView *netBadView;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isLostPackage; // 严重丢包
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isBitError; // bit error
|
|
|
-
|
|
|
-@property (nonatomic, strong) LOTAnimationView *animationView;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isCloseRoom; // 是否直播结束
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSLiveEndView *endView; // 直播结束显示的画面
|
|
|
-
|
|
|
-@property (nonatomic, strong) KSShopCardView *cardView;
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveAnimationView *enterAnimationView;
|
|
|
-
|
|
|
-@property (nonatomic, assign) NSTimeInterval lastSendMsgTime;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isOtherLogin; // 是否被顶掉
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveApplyView *applyView; // 未申请
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveApplyingView *applyingView; // 申请中
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isPauseLive;
|
|
|
-
|
|
|
-@property (nonatomic, strong) ShareLiveDisplayView *shareView;
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-// 用于记录点赞消息连续点击的次数
|
|
|
-static int clickPraiseBtnTimes = 0;
|
|
|
-
|
|
|
-@implementation LiveVideoRoomViewController
|
|
|
-
|
|
|
-- (instancetype)init {
|
|
|
- self = [super init];
|
|
|
- if (self) {
|
|
|
- [self defaultConfig];
|
|
|
- }
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)defaultConfig {
|
|
|
- self.enableChat = YES;
|
|
|
- self.enableSeat = YES;
|
|
|
- self.enableLike = YES;
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
- self.isCreaterInRoom = NO; // 默认老师不在房间
|
|
|
- self.isImConnected = [USER_MANAGER checkIMConnected];
|
|
|
- self.isCloseRoom = NO;
|
|
|
- self.isOtherLogin = NO;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)viewDidLoad {
|
|
|
- [super viewDidLoad];
|
|
|
- // Do any additional setup after loading the view.
|
|
|
- self.ks_prefersNavigationBarHidden = YES;
|
|
|
- [self registerNotification];
|
|
|
- [self setupUI];
|
|
|
- if (self.isImConnected) {
|
|
|
- [self connectService];
|
|
|
- }
|
|
|
- else {
|
|
|
- MJWeakSelf;
|
|
|
- [USER_MANAGER connectionIMCallback:^(BOOL isSuccess) {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- [weakSelf connectService];
|
|
|
- });
|
|
|
- }];
|
|
|
- }
|
|
|
- [self countUMEvent];
|
|
|
- [self judgeAutoClose];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)countUMEvent {
|
|
|
- [USER_MANAGER sendUMEvent:@"klx_live"];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)muteAllAudio {
|
|
|
- if (self.room) {
|
|
|
- [self.room muteAllRemoteAudio:YES];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)IMConnetedCallback {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- // IM 连接成功回调
|
|
|
- if (self.hasSendWelcomeMessage) { // 如果已经发送了进入消息
|
|
|
- // 查询是否直播间开启
|
|
|
- [KSNetworkingManager liveRoomJoinRoomRequest:KS_GET roomUid:self.roomId success:^(NSDictionary * _Nonnull dic) {
|
|
|
- if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
|
|
|
- // 回调信息
|
|
|
- MJWeakSelf;
|
|
|
- [self notiferJoinSuccessToServiceCallback:^{
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"IM连接成功"];
|
|
|
- [weakSelf sendWelcomeMessage];
|
|
|
- }];
|
|
|
- }
|
|
|
- else {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
|
|
|
- [self quitRoom];
|
|
|
- }
|
|
|
- } faliure:^(NSError * _Nonnull error) {
|
|
|
-
|
|
|
- }];
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)sendWelcomeMessage {
|
|
|
- [[RCIMClient sharedRCIMClient] joinExistChatRoom:self.roomId messageCount:-1 success:^{
|
|
|
- KSLiveChatroomWelcome *joinChatroomMessage = [[KSLiveChatroomWelcome alloc] init];
|
|
|
- [joinChatroomMessage setMsgId:[RCIM sharedRCIM].currentUserInfo.userId];
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:joinChatroomMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
- [weakSelf showEnterMessageAndJoinRTCRoom];
|
|
|
- }];
|
|
|
- } error:^(RCErrorCode status) {
|
|
|
- NSLog(@"error code %zd" ,status);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showEnterMessageAndJoinRTCRoom {
|
|
|
-
|
|
|
- NSString *contentString = [NSString stringWithFormat:@"%@ 进入直播间",UserDefault(NicknameKey)];
|
|
|
- [self showAnimationView:YES showMessag:contentString];
|
|
|
- [self joinRTCRoom];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)leaveRTCRoomCallback:(void(^)(BOOL success))callback {
|
|
|
- [[RCRTCEngine sharedInstance] leaveRoom:^(BOOL isSuccess, RCRTCCode code) {
|
|
|
- callback(isSuccess);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)joinRTCRoom {
|
|
|
-
|
|
|
- // 如果当前加入了房间 只刷新或者退出
|
|
|
- if (self.room && self.liveRoleType == RCRTCLiveRoleTypeBroadcaster) {
|
|
|
- [self connectHostWithStatus:NO];
|
|
|
- }
|
|
|
- else {
|
|
|
- [self setRoleType];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)judgeAutoClose {
|
|
|
- if (self.isTempRoom == NO) {
|
|
|
- self.timeManager.autoCloseNetworkRoomTime = [self getCloseTime];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)liveroomLogOut {
|
|
|
- if (self.isOtherLogin) {
|
|
|
- return;
|
|
|
- }
|
|
|
- self.isOtherLogin = YES;
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"该账号在其他设备上登录"];
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitRoom];
|
|
|
- [[NSNotificationCenter defaultCenter] postNotificationName:@"liveroomBackRefresh" object:nil];
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-- (void)liveroomQuit {
|
|
|
- if (self.isOtherLogin) {
|
|
|
- return;
|
|
|
- }
|
|
|
- self.isOtherLogin = YES;
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitRoom];
|
|
|
- [[NSNotificationCenter defaultCenter] postNotificationName:@"liveroomBackRefresh" object:nil];
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-- (void)registerNotification {
|
|
|
- [KSChatroomMessageCenter registerMessageTypes];
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMessageNotification:) name:OnReceiveChatroomMessageNotification object:nil];
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomLogOut) name:@"liveroomLogout" object:nil];
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomQuit) name:@"liveroomQuit" object:nil];
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(IMConnetedCallback) name:@"RongIMConnected" object:nil];
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(muteAllAudio) name:@"muteLiveAudio" object:nil];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setupUI {
|
|
|
- CGSize size = self.view.bounds.size;
|
|
|
- self.view.backgroundColor = HexRGB(0x25292e);
|
|
|
-
|
|
|
- [self.view addSubview:self.emptyView];
|
|
|
-
|
|
|
- [self.view addSubview:self.endView];
|
|
|
-
|
|
|
- // 视图主容器
|
|
|
- [self.view addSubview:self.videoContainerView];
|
|
|
- [self.videoContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.top.bottom.right.mas_equalTo(self.view);
|
|
|
- }];
|
|
|
-
|
|
|
- [self.videoContainerView addSubview:self.videoView];
|
|
|
-
|
|
|
- [self.videoContainerView addSubview:self.netBadView];
|
|
|
-
|
|
|
- [self.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.top.bottom.right.mas_equalTo(self.view);
|
|
|
- }];
|
|
|
-
|
|
|
- [self.emptyView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.top.bottom.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
- self.emptyView.hidden = YES;
|
|
|
- // 直播结束的画面
|
|
|
- [self.endView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.top.bottom.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
- self.endView.hidden = YES;
|
|
|
-
|
|
|
- [self.netBadView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.top.bottom.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
- self.netBadView.hidden = YES;
|
|
|
-
|
|
|
- [self.view addSubview:self.headView];
|
|
|
- self.headView.boardcastName.text = [NSString returnNoNullStringWithString:self.createrName];
|
|
|
- if (![NSString isEmptyString:self.createrAvatal]) {
|
|
|
- [self.headView.boardcastAvatal sd_setImageWithURL:[NSURL URLWithString:[self.createrAvatal getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"teacher_logo"]];
|
|
|
- }
|
|
|
- [self countLikeMessageCount];
|
|
|
- [self countMemberCount];
|
|
|
- [self.headView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.view);
|
|
|
- make.height.mas_equalTo(80);
|
|
|
- if (@available(iOS 11.0, *)) {
|
|
|
- make.top.mas_equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(0);
|
|
|
- } else {
|
|
|
- // Fallback on earlier versions
|
|
|
- make.top.mas_equalTo(self.view.mas_top).offset(0);
|
|
|
- }
|
|
|
- }];
|
|
|
- [self.view addSubview:self.messageContentView];
|
|
|
-
|
|
|
- if (self.hideCartButton == NO) {
|
|
|
- [self.videoContainerView addSubview:self.animationView];
|
|
|
- [self.animationView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- if (@available(iOS 11.0, *)) {
|
|
|
- make.bottom.mas_equalTo(self.videoContainerView.mas_safeAreaLayoutGuideBottom).offset(-14);
|
|
|
- } else {
|
|
|
- // Fallback on earlier versions
|
|
|
- make.bottom.mas_equalTo(self.videoContainerView.mas_bottom).offset(-14);
|
|
|
- }
|
|
|
- make.centerX.mas_equalTo(self.videoContainerView.mas_right).offset(-84);
|
|
|
- make.width.mas_equalTo(48);
|
|
|
- make.height.mas_equalTo(56);
|
|
|
- }];
|
|
|
- [self.animationView play];
|
|
|
- }
|
|
|
- [self.view addSubview:self.bottomView];
|
|
|
- self.bottomView.hideCartVButton = self.hideCartButton;
|
|
|
- [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.view);
|
|
|
- if (@available(iOS 11.0, *)) {
|
|
|
- make.bottom.mas_equalTo(self.view.mas_safeAreaLayoutGuideBottom).offset(-10);
|
|
|
- } else {
|
|
|
- // Fallback on earlier versions
|
|
|
- make.bottom.mas_equalTo(self.view.mas_bottom).offset(-10);
|
|
|
- }
|
|
|
- make.height.mas_equalTo(44);
|
|
|
- }];
|
|
|
-
|
|
|
- [self.messageContentView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.mas_equalTo(self.view.mas_left);
|
|
|
- make.right.mas_equalTo(self.view.mas_right);
|
|
|
- make.bottom.mas_equalTo(self.bottomView.mas_top).offset(-10);
|
|
|
- make.height.mas_equalTo(180);
|
|
|
- }];
|
|
|
- [self.view addSubview:self.inputBar];
|
|
|
- [_inputBar setBackgroundColor: [UIColor whiteColor]];
|
|
|
-
|
|
|
- [_inputBar setFrame:CGRectMake(0, kScreenHeight, size.width , 50)];
|
|
|
- [_inputBar setHidden:YES];
|
|
|
-
|
|
|
- [self.messageContentView addSubview:self.conversationMessageTableView];
|
|
|
- [self.conversationMessageTableView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.top.mas_equalTo(self.messageContentView);
|
|
|
- make.width.mas_equalTo(KPortraitWidth);
|
|
|
- make.bottom.mas_equalTo(self.messageContentView.mas_bottom);
|
|
|
- }];
|
|
|
-
|
|
|
- UITapGestureRecognizer *resetBottomTapGesture =[[UITapGestureRecognizer alloc]
|
|
|
- initWithTarget:self
|
|
|
- action:@selector(resetBottomGesture:)];
|
|
|
- resetBottomTapGesture.delegate = self;
|
|
|
- [self.view addGestureRecognizer:resetBottomTapGesture];
|
|
|
-
|
|
|
-// if (self.isTempRoom) {
|
|
|
-// self.bottomView.hideShareButton = NO;
|
|
|
-// }
|
|
|
-// else {
|
|
|
-// self.bottomView.hideShareButton = YES;
|
|
|
-// }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)connectService {
|
|
|
- [self setRoleType];
|
|
|
- [self joinChatRoom];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)joinChatRoom {
|
|
|
- [[RCIMClient sharedRCIMClient] joinChatRoom:self.roomId messageCount:-1 success:^{
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- [self addConstMessage];
|
|
|
- });
|
|
|
- KSLiveChatroomWelcome *joinChatroomMessage = [[KSLiveChatroomWelcome alloc] init];
|
|
|
- [joinChatroomMessage setMsgId:[RCIM sharedRCIM].currentUserInfo.userId];
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:joinChatroomMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
- weakSelf.hasSendWelcomeMessage = YES;
|
|
|
- NSString *contentString = [NSString stringWithFormat:@"%@ 进入直播间",UserDefault(NicknameKey)];;
|
|
|
- [weakSelf showAnimationView:YES showMessag:contentString];
|
|
|
- }];
|
|
|
- // 加入成功发送消息
|
|
|
- } error:^(RCErrorCode status) {
|
|
|
- if (status == RC_CHATROOM_NOT_EXIST || status == KICKED_FROM_CHATROOM || status == RC_PARAMETER_INVALID_CHATROOM) {
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"加入聊天室失败"];
|
|
|
- });
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)viewWillAppear:(BOOL)animated {
|
|
|
- [super viewWillAppear:animated];
|
|
|
- [UIApplication sharedApplication].idleTimerDisabled = YES;
|
|
|
- [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
|
|
|
- [IQKeyboardManager sharedManager].enable = NO;
|
|
|
- [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
|
|
|
- // 重新渲染view
|
|
|
- KSDragWindowManager *manager = [KSDragWindowManager sharedManager];
|
|
|
- if (manager.hasShowWindow) {
|
|
|
- [manager resignDragWindow];
|
|
|
- }
|
|
|
- if (self.hasShowSuspendView) {
|
|
|
- KSLiveStreamVideo *mainVideo = nil;
|
|
|
- if (self.videoView.streamId) {
|
|
|
- NSMutableArray *steamArray = [self.streamVideos mutableCopy];
|
|
|
- for (KSLiveStreamVideo *streamVideo in steamArray) {
|
|
|
- if ([streamVideo.streamId isEqualToString:self.videoView.streamId]) {
|
|
|
- mainVideo = streamVideo;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (mainVideo) {
|
|
|
- [self.videoView addSubview:mainVideo.canvesView];
|
|
|
- [mainVideo.canvesView mas_updateConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.bottom.top.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
- }
|
|
|
- _hasShowSuspendView = NO;
|
|
|
- }
|
|
|
- if (self.room) {
|
|
|
- [self.room muteAllRemoteAudio:NO];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)viewWillDisappear:(BOOL)animated {
|
|
|
- [super viewWillDisappear:animated];
|
|
|
- [UIApplication sharedApplication].idleTimerDisabled = NO;
|
|
|
- [IQKeyboardManager sharedManager].enableAutoToolbar = YES;
|
|
|
- [IQKeyboardManager sharedManager].enable = YES;
|
|
|
- if (@available(iOS 13.0, *)) {
|
|
|
- [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDarkContent;
|
|
|
- } else {
|
|
|
- // Fallback on earlier versions
|
|
|
- [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
|
|
|
- }
|
|
|
-
|
|
|
- // 退出房间才停止定时器
|
|
|
- if (_timeManager) {
|
|
|
- [_timeManager stopDurationTimer];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 刷新seatView
|
|
|
-- (void)renderSeatView {
|
|
|
-
|
|
|
- NSMutableArray *seatArray = [NSMutableArray array];
|
|
|
- NSArray *remoteUserArray = [self.room.remoteUsers mutableCopy];
|
|
|
- for (RCRTCRemoteUser *user in remoteUserArray) {
|
|
|
- if (![user.userId isEqualToString:self.videoView.streamUserId] && ![user.userId isEqualToString:self.createrId] && ![user.userId containsString:@"rc_mc_"]) {
|
|
|
- [seatArray addObject:user.userId];
|
|
|
- }
|
|
|
- }
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING && ![seatArray containsObject:UserDefault(IM_USERID)]) {
|
|
|
- [seatArray addObject:UserDefault(IM_USERID)];
|
|
|
- }
|
|
|
-
|
|
|
- if (seatArray.count) {
|
|
|
- if (![self.videoContainerView.subviews containsObject:self.seatContainer]) {
|
|
|
- [self.videoContainerView addSubview:self.seatContainer];
|
|
|
- }
|
|
|
- [self updateSeatContainerConstraint];
|
|
|
-
|
|
|
- self.seatContainer.seatMemberArray = [NSMutableArray arrayWithArray:seatArray];
|
|
|
- [self.seatContainer refreshSeatUI];
|
|
|
- }
|
|
|
- else {
|
|
|
- [self removeSeatContainer];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)updateSeatContainerConstraint {
|
|
|
- [self.seatContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.videoContainerView);
|
|
|
- make.top.mas_equalTo(self.headView.mas_bottom).offset(0);
|
|
|
- make.height.mas_equalTo(70);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-// 移除连麦视图
|
|
|
-- (void)removeSeatContainer {
|
|
|
- if ([self.videoContainerView.subviews containsObject:self.seatContainer]) {
|
|
|
- [self.seatContainer removeFromSuperview];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)countLikeMessageCount {
|
|
|
- NSInteger count = self.likeCount;
|
|
|
- NSString *desc = @"";
|
|
|
- if (count > 10000) {
|
|
|
- count = count / 10000;
|
|
|
- desc = [NSString stringWithFormat:@"本场点赞%zd万+",count];
|
|
|
- }
|
|
|
- else {
|
|
|
- desc = [NSString stringWithFormat:@"本场点赞%zd",count];
|
|
|
- }
|
|
|
- self.headView.likeCount.text = desc;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setRoleType {
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
- [self hideApplyingView];
|
|
|
- // 1.设置切换听筒为扬声器
|
|
|
- [self.engine setDefaultAudioRouteToSpeaker:YES];
|
|
|
- // 2.加入RTC房间
|
|
|
- [self joinLiveRoom];
|
|
|
-}
|
|
|
-
|
|
|
-// 观众上下麦
|
|
|
-- (void)connectHostWithStatus:(BOOL)isConnect {
|
|
|
-
|
|
|
- // 转换中,不再处理转换身份
|
|
|
- if (self.isTransferRole) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // 如果需要切换的身份和当前身份相同 拦截
|
|
|
- if (isConnect && self.liveRoleType == RCRTCLiveRoleTypeBroadcaster) {
|
|
|
- return;
|
|
|
- }
|
|
|
- else if (isConnect == NO && self.liveRoleType == RCRTCLiveRoleTypeAudience) {
|
|
|
- return;
|
|
|
- }
|
|
|
- self.isTransferRole = YES;
|
|
|
- // 清理当前视图
|
|
|
- [self removeSeatContainer];
|
|
|
- [self clearVideoViewSource];
|
|
|
- if (isConnect) {
|
|
|
- // 开启麦克风采集
|
|
|
- [self.engine.defaultAudioStream setMicrophoneDisable:NO];
|
|
|
- NSArray *streams = @[self.engine.defaultAudioStream];
|
|
|
- MJWeakSelf;
|
|
|
- [self.room.localUser switchToBroadcaster:streams onSucceed:^(RCRTCLiveInfo * _Nonnull liveInfo) {
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
-
|
|
|
- //3.切换成功, 订阅远端用户流
|
|
|
- strongSelf.liveRoleType = RCRTCLiveRoleTypeBroadcaster;
|
|
|
- NSMutableArray *streamArray = [NSMutableArray array];
|
|
|
- NSArray *remoteUserArray = [strongSelf.room.remoteUsers mutableCopy];
|
|
|
- for (RCRTCRemoteUser *user in remoteUserArray) {
|
|
|
- if (remoteUserArray.count) {
|
|
|
- [streamArray addObjectsFromArray:user.remoteStreams];
|
|
|
- }
|
|
|
- }
|
|
|
- if (streamArray.count) {
|
|
|
- [strongSelf subscribeRemoteResource:streamArray];
|
|
|
- }
|
|
|
- else {
|
|
|
- [strongSelf updateVideoViewContainer];
|
|
|
- }
|
|
|
-
|
|
|
- strongSelf.micStatus = MICSTATUS_CONNECTING;
|
|
|
- // 刷新麦位状态
|
|
|
- });
|
|
|
-
|
|
|
- } onFailed:^(RCRTCCode code) {
|
|
|
-
|
|
|
- NSLog(@"------- up error code %ld", code);
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- if (code == RCRTCCodeSwitchRoleSameRoleError) {
|
|
|
- weakSelf.liveRoleType = RCRTCLiveRoleTypeBroadcaster;
|
|
|
- // 失败
|
|
|
- weakSelf.micStatus = MICSTATUS_CONNECTING;
|
|
|
- // 刷新麦位状态
|
|
|
- [weakSelf renderSeatView];
|
|
|
- }
|
|
|
- else {
|
|
|
- // 失败
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"上麦失败"];
|
|
|
- weakSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- [weakSelf renderSeatView];
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- } onKicked:^{
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- // 被踢出
|
|
|
- [weakSelf kickOutLiveRoom];
|
|
|
- });
|
|
|
-
|
|
|
- }];
|
|
|
- }
|
|
|
- else { // 观众下麦
|
|
|
- MJWeakSelf;
|
|
|
- [self.room.localUser switchToAudienceOnSucceed:^{
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
- strongSelf.liveRoleType = RCRTCLiveRoleTypeAudience;
|
|
|
- [strongSelf.engine.defaultAudioStream setMicrophoneDisable:YES];
|
|
|
-
|
|
|
- NSMutableArray *streamArray = [NSMutableArray array];
|
|
|
- NSArray *remoteUserArray = [strongSelf.room.remoteUsers mutableCopy];
|
|
|
-
|
|
|
- for (RCRTCRemoteUser *user in remoteUserArray) {
|
|
|
- if (user.remoteStreams.count) {
|
|
|
- [streamArray addObjectsFromArray:user.remoteStreams];
|
|
|
- }
|
|
|
- }
|
|
|
- strongSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
-
|
|
|
- if (streamArray.count) {
|
|
|
- [strongSelf subscribeRemoteResource:streamArray];
|
|
|
- }
|
|
|
- else {
|
|
|
- [strongSelf updateVideoViewContainer];
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // 刷新麦位状态
|
|
|
- // 发送下麦消息
|
|
|
- [weakSelf sendDownSeatMessage];
|
|
|
- });
|
|
|
-
|
|
|
- } onFailed:^(RCRTCCode code) {
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- NSLog(@"------- down error code %ld", code);
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- if (code == RCRTCCodeSwitchRoleSameRoleError) {
|
|
|
- weakSelf.liveRoleType = RCRTCLiveRoleTypeAudience;
|
|
|
- weakSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- }
|
|
|
- else {
|
|
|
- // 失败
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"下麦失败"];
|
|
|
- weakSelf.micStatus = MICSTATUS_CONNECTING;
|
|
|
- }
|
|
|
- // 刷新麦位状态
|
|
|
- [weakSelf renderSeatView];
|
|
|
- });
|
|
|
-
|
|
|
- } onKicked:^{
|
|
|
- weakSelf.isTransferRole = NO;
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- // 被踢出
|
|
|
- [weakSelf kickOutLiveRoom];
|
|
|
- });
|
|
|
- }];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)kickOutLiveRoom {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已被踢出直播间"];
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitRoom];
|
|
|
- });
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)countMemberCount {
|
|
|
- NSInteger count = self.totalCount;
|
|
|
- NSString *desc = @"";
|
|
|
- if (count > 10000) {
|
|
|
- count = count / 10000;
|
|
|
- desc = [NSString stringWithFormat:@"%zd万+人",count];
|
|
|
- }
|
|
|
- else {
|
|
|
- desc = [NSString stringWithFormat:@"%zd人",count];
|
|
|
- }
|
|
|
- self.headView.roomMemberCount.text = desc;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)clearVideoViewSource {
|
|
|
- self.videoView.streamUserId = @"";
|
|
|
- self.videoView.streamTag = @"";
|
|
|
- self.videoView.streamId = @"";
|
|
|
-}
|
|
|
-
|
|
|
-// 清空视图
|
|
|
-- (void)clearRemoteContainer {
|
|
|
- [self.streamVideos removeAllObjects];
|
|
|
- [self.videoView removeAllSubViews];
|
|
|
- [self clearVideoViewSource];
|
|
|
- [self removeSeatContainer];
|
|
|
-}
|
|
|
-
|
|
|
-// 更新视图
|
|
|
-- (void)updateVideoViewContainer {
|
|
|
- NSMutableArray *steamArray = [self.streamVideos mutableCopy];
|
|
|
-
|
|
|
- if (steamArray.count > 0) {
|
|
|
-
|
|
|
- // 渲染主播的流 优先显示主播的共享流
|
|
|
- KSLiveStreamVideo *mainVideo = nil;
|
|
|
- for (KSLiveStreamVideo *videoSource in steamArray) {
|
|
|
- if ([videoSource.userId isEqualToString:self.createrId]) { // 主屏只渲染老师
|
|
|
- if ([videoSource.streamTag isEqualToString:@"screenshare"]) { // 如果是共享流
|
|
|
- if (![self.videoView.streamId isEqualToString:videoSource.streamId]) { // 主屏渲染不同 则重新渲染
|
|
|
- mainVideo = videoSource;
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- else if ([videoSource.streamTag isEqualToString:@"RongCloudRTC"]) { // 默认流
|
|
|
- if (![self.videoView.streamId isEqualToString:videoSource.streamId]) { // 主屏渲染不同 则重新渲染
|
|
|
- mainVideo = videoSource;
|
|
|
- }
|
|
|
- }
|
|
|
- else { // 其他流
|
|
|
- if (mainVideo == nil) { // 如果暂未遍历出其他视频流 先取一个作为主屏展示流
|
|
|
- if (![self.videoView.streamId isEqualToString:videoSource.streamId]) { // 主屏渲染不同 则重新渲染
|
|
|
- mainVideo = videoSource;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- // 如果需要渲染主屏
|
|
|
- if (mainVideo) {
|
|
|
- [self.videoView removeAllSubViews];
|
|
|
- self.videoView.streamUserId = mainVideo.userId;
|
|
|
- self.videoView.streamId = mainVideo.streamId;
|
|
|
- self.videoView.streamTag = mainVideo.streamTag;
|
|
|
- mainVideo.canvesView.tag = 10000;
|
|
|
- [self.videoView addSubview:mainVideo.canvesView];
|
|
|
- [mainVideo.canvesView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.bottom.top.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- [self changeEmptyStatusView];
|
|
|
- // 刷新 seatView
|
|
|
- [self renderSeatView];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)removeViewSubViews:(UIView *)container {
|
|
|
- while (container.subviews.count) {
|
|
|
- [container.subviews.lastObject removeFromSuperview];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)changeEmptyStatusView {
|
|
|
- if (self.isCreaterInRoom) {
|
|
|
- if (self.isCreaterVideoEnable) {
|
|
|
- self.emptyView.hidden = YES;
|
|
|
- }
|
|
|
- else if (self.isCreaterVideoEnable == NO && self.isCreaterAudioEnable == YES) {
|
|
|
- // 主播关闭了摄像头
|
|
|
- [self showEmptyViewDisplay:YES];
|
|
|
- }
|
|
|
- else { // 休息一下
|
|
|
- [self showEmptyViewDisplay:NO];
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- // 无主播
|
|
|
- [self.videoView removeAllSubViews];
|
|
|
- [self showEmptyViewDisplay:NO];
|
|
|
- }
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark ---- RCRTCRoomEventDelegate
|
|
|
-// 远端发布流
|
|
|
-- (void)didPublishStreams:(NSArray<RCRTCInputStream *> *)streams {
|
|
|
- [self subscribeRemoteResource:streams];
|
|
|
- NSLog(@"didPublishStreams --------");
|
|
|
-}
|
|
|
-
|
|
|
-// 订阅远端流
|
|
|
-- (void)subscribeRemoteResource:(NSArray<RCRTCInputStream *> *)streams {
|
|
|
- [self subscribeRemoteResource:streams isTiny:NO];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)subscribeRemoteResource:(NSArray<RCRTCInputStream *> *)streams isTiny:(BOOL)isTiny {
|
|
|
- // 订阅房间中远端用户音视频流资源
|
|
|
- NSArray *tinyStream = isTiny ? streams : @[];
|
|
|
- NSArray *ordinaryStream = isTiny ? @[] : streams;
|
|
|
- [self.room.localUser subscribeStream:ordinaryStream
|
|
|
- tinyStreams:tinyStream
|
|
|
- completion:^(BOOL isSuccess, RCRTCCode desc) {
|
|
|
- if (desc != RCRTCCodeSuccess) {
|
|
|
- NSString *errorStr = [NSString stringWithFormat:@"订阅远端流失败:%ld", (long) desc];
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:errorStr];
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // 创建并设置远端视频预览视图
|
|
|
- for (RCRTCInputStream *stream in streams) {
|
|
|
- if ([stream.userId isEqualToString:self.createrId]) {
|
|
|
- self.isPauseLive = NO;
|
|
|
- }
|
|
|
- if (stream.mediaType == RTCMediaTypeVideo) {
|
|
|
- if ([stream.userId isEqualToString:self.createrId]) { // 只渲染老师的流
|
|
|
- self.isCreaterVideoEnable = YES;
|
|
|
- [self setupRemoteViewWithStream:stream];
|
|
|
- }
|
|
|
- }
|
|
|
- if (stream.mediaType == RTCMediaTypeAudio && [stream.userId isEqualToString:self.createrId]) {
|
|
|
- self.isCreaterAudioEnable = YES;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- [self updateVideoViewContainer];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-// 创建并设置远端视频预览视图
|
|
|
-- (KSLiveStreamVideo *)setupRemoteViewWithStream:(RCRTCInputStream *)stream {
|
|
|
-
|
|
|
- KSLiveStreamVideo *sVideo = [self creatStreamVideoWithStreamId:stream.streamId userId:stream.userId tag:stream.tag];
|
|
|
- sVideo.userId = stream.userId;
|
|
|
- RCRTCVideoView *remoteView = (RCRTCVideoView *) sVideo.canvesView;
|
|
|
-
|
|
|
- //设置视频流的渲染视图
|
|
|
- [(RCRTCVideoInputStream *) stream setVideoView:remoteView];
|
|
|
- return sVideo;
|
|
|
-}
|
|
|
-
|
|
|
-// 远端用户取消发布资源
|
|
|
-- (void)didUnpublishStreams:(NSArray<RCRTCInputStream *> *)streams {
|
|
|
- [self unsubscribeRemoteResource:streams orStreamId:nil];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)stream:(RCRTCInputStream *)stream didVideoEnable:(BOOL)enable {
|
|
|
- NSLog(@"----- video --- staus %d", enable);
|
|
|
-}
|
|
|
-
|
|
|
-- (void)stream:(RCRTCInputStream *)stream didAudioMute:(BOOL)mute {
|
|
|
- NSLog(@"----- audio --- staus %d", mute);
|
|
|
- if ([stream.userId isEqualToString:self.createrId]) {
|
|
|
- if (mute) {
|
|
|
- self.isCreaterAudioEnable = NO;
|
|
|
- }
|
|
|
- else {
|
|
|
- self.isCreaterAudioEnable = YES;
|
|
|
- }
|
|
|
- [self changeEmptyStatusView];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)didOfflineUser:(RCRTCRemoteUser *)user {
|
|
|
- [self removeRemoteVideoWithUserId:user.userId];
|
|
|
- [self renderSeatView];
|
|
|
-}
|
|
|
-
|
|
|
-// 判断是否已有预览视图
|
|
|
-- (KSLiveStreamVideo *)creatStreamVideoWithStreamId:(NSString *)streamId userId:(NSString *)userId tag:(NSString *)streamTag {
|
|
|
- KSLiveStreamVideo *sVideo = [self fetchStreamVideoWithStreamId:streamId];
|
|
|
- if (!sVideo) {
|
|
|
- sVideo = [[KSLiveStreamVideo alloc] initWithStreamId:streamId streamUserId:userId streamTag:streamTag];
|
|
|
- [self.streamVideos insertObject:sVideo atIndex:0];
|
|
|
- }
|
|
|
- return sVideo;
|
|
|
-}
|
|
|
-
|
|
|
-// 根据 streamId 确认唯一的音视频流
|
|
|
-- (KSLiveStreamVideo *)fetchStreamVideoWithStreamId:(NSString *)streamId {
|
|
|
- NSMutableArray *streamArray = [self.streamVideos mutableCopy];
|
|
|
- for (KSLiveStreamVideo *sVideo in streamArray) {
|
|
|
- if ([streamId isEqualToString:sVideo.streamId]) {
|
|
|
- return sVideo;
|
|
|
- }
|
|
|
- }
|
|
|
- return nil;
|
|
|
-}
|
|
|
-
|
|
|
-// 远端掉线/离开回掉调用,删除远端用户的所有音视频流
|
|
|
-- (void)fetchStreamVideoOffLineWithStreamId:(NSString *)streamId {
|
|
|
-
|
|
|
- NSArray *arr = [NSArray arrayWithArray:self.streamVideos];
|
|
|
- for (KSLiveStreamVideo *sVideo in arr) {
|
|
|
- if ([streamId isEqualToString:sVideo.streamId]) {
|
|
|
- if (sVideo) {
|
|
|
- [sVideo.canvesView removeFromSuperview];
|
|
|
- [self.streamVideos removeObject:sVideo];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- [self updateVideoViewContainer];
|
|
|
-}
|
|
|
-// 远端用户切换身份(主播接收)
|
|
|
-- (void)didSwitchRoleWithUser:(RCRTCRemoteUser *)user roleType:(RCRTCLiveRoleType)roleType {
|
|
|
- if (roleType == RCRTCLiveRoleTypeAudience) {
|
|
|
- [self renderSeatView];
|
|
|
- }
|
|
|
-
|
|
|
- NSLog(@"didSwitchRoleWithUser --------");
|
|
|
-}
|
|
|
-
|
|
|
-- (void)judgeRefreshSeatView:(NSString *)userId {
|
|
|
- BOOL needRefresh = NO;
|
|
|
- if (_seatContainer) {
|
|
|
- if (self.seatContainer.seatMemberArray.count && [self.videoContainerView.subviews containsObject:self.seatContainer]) {
|
|
|
- NSMutableArray *memerArray = [self.seatContainer.seatMemberArray mutableCopy];
|
|
|
- for (NSString *memberId in memerArray) {
|
|
|
- if ([userId isEqualToString:memberId]) {
|
|
|
- needRefresh = YES;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (needRefresh) {
|
|
|
- [self renderSeatView];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 主播加入房间 (观众接收)
|
|
|
-- (void)didJoinUser:(RCRTCRemoteUser *)user {
|
|
|
- if ([user.userId isEqualToString:self.createrId]) { // 当主播重新进入房间需要重置连麦状态
|
|
|
- self.isCreaterInRoom = YES;
|
|
|
- // 重置连麦状态
|
|
|
-// [self resetMicWaitToNomal];
|
|
|
- // 刷新顶部视图
|
|
|
- }
|
|
|
- else {
|
|
|
-// [self renderSeatView];
|
|
|
- }
|
|
|
- NSLog(@"didJoinUser --------");
|
|
|
-}
|
|
|
-
|
|
|
-// 主播离开房间 (观众接收)
|
|
|
-- (void)didLeaveUser:(RCRTCRemoteUser *)user {
|
|
|
- [self removeRemoteVideoWithUserId:user.userId]; // 移除对应的视频
|
|
|
- if ([user.userId isEqualToString:self.createrId]) { // 如果是老师
|
|
|
-
|
|
|
- self.isCreaterInRoom = NO;
|
|
|
- [self resetMicWaitToNomal];
|
|
|
- [self tipsTeacherLeaveRoom];
|
|
|
- [self clearVideoView];
|
|
|
- [self hideTipsView];
|
|
|
- [self showEmptyViewDisplay:NO];
|
|
|
- }
|
|
|
- else {
|
|
|
- [self renderSeatView];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)removeRemoteVideoWithUserId:(NSString *)userId {
|
|
|
- NSArray *arr = [NSArray arrayWithArray:self.streamVideos];
|
|
|
- for (KSLiveStreamVideo *sVideo in arr) {
|
|
|
- if ([userId isEqualToString:sVideo.userId]) {
|
|
|
- if (sVideo) {
|
|
|
- [sVideo.canvesView removeFromSuperview];
|
|
|
- [self.streamVideos removeObject:sVideo];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)clearVideoView {
|
|
|
- [self clearVideoViewSource];
|
|
|
- [self.videoView removeAllSubViews];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)resetConnectionStatus {
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
|
-
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self connectHostWithStatus:NO];
|
|
|
- });
|
|
|
- }
|
|
|
- else {
|
|
|
- [self removeSeatContainer];
|
|
|
- }
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)resetMicWaitToNomal {
|
|
|
- if (self.micStatus == MICSTATUS_WAITING) {
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)tipsTeacherLeaveRoom {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师已离开房间"];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#pragma mark - KSChatInputBarControlDelegate
|
|
|
-// 根据inputBar 回调来修改页面布局
|
|
|
-- (void)onInputBarControlContentSizeChanged:(CGRect)frame withAnimationDuration:(CGFloat)duration andAnimationCurve:(UIViewAnimationCurve)curve {
|
|
|
- CGRect originFrame = _inputBar.frame;
|
|
|
- __weak __typeof(&*self)weakSelf = self;
|
|
|
- // 目前只使用y值即可 -- 只修改messageContentView高度,让展示消息view和输入框随之移动
|
|
|
- [UIView animateWithDuration:duration animations:^{
|
|
|
- [UIView setAnimationCurve:curve];
|
|
|
- [weakSelf.inputBar setFrame:CGRectMake(0, frame.origin.y - originFrame.size.height, originFrame.size.width, originFrame.size.height)];
|
|
|
- [UIView commitAnimations];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-// 发送消息
|
|
|
-- (void)onTouchSendButton:(NSString *)text {
|
|
|
- if (self.blacklistFlag == YES) {
|
|
|
- [self setDefaultBottomViewStatus];
|
|
|
- return;
|
|
|
- }
|
|
|
- NSDate *date = [NSDate date];
|
|
|
- NSTimeInterval currentInterval = [date timeIntervalSince1970];
|
|
|
- if (currentInterval - self.lastSendMsgTime < 3) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您说话太快啦"];
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (self.lastSendMsgTime == 0) {
|
|
|
- self.lastSendMsgTime = currentInterval;
|
|
|
- }
|
|
|
-
|
|
|
- if (text.length > 40) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"聊天消息需在40个字以内哦"];
|
|
|
- return;
|
|
|
- }
|
|
|
- self.lastSendMsgTime = currentInterval;
|
|
|
- [self touristSendMessage:text];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)touristSendMessage:(NSString *)text {
|
|
|
-
|
|
|
- RCTextMessage *rcTextMessage = [RCTextMessage messageWithContent:text];
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:rcTextMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- [weakSelf setDefaultBottomViewStatus];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark ---- RTC
|
|
|
-- (void)joinLiveRoom {
|
|
|
-
|
|
|
- // 1.配置房间
|
|
|
- RCRTCRoomConfig *config = [[RCRTCRoomConfig alloc] init];
|
|
|
- config.roomType = RCRTCRoomTypeLive;
|
|
|
- config.liveType = RCRTCLiveTypeAudioVideo;
|
|
|
- config.roleType = RCRTCLiveRoleTypeAudience;
|
|
|
- __weak typeof(self) weakSelf = self;
|
|
|
- [self.engine joinRoom:self.roomId config:config completion:^(RCRTCRoom * _Nullable room, RCRTCCode code) {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
- if (code == RCRTCCodeSignalServerNotConnect || code == RCRTCCodeParameterError || code == RCRTCCodeNotInRTCRoom || code == RCRTCCodeRTCTokenIsNull || code == RCRTCCodeHttpTimeoutError || code == RCRTCCodeHttpError || code == RCRTCCodeVoIPNotAvailable) {
|
|
|
- NSLog(@"%@",[NSString stringWithFormat:@"加入失败 code %ld",code]);
|
|
|
- }
|
|
|
- else { // 加入直播间成功
|
|
|
- [strongSelf notiferJoinSuccessToServiceCallback:^{
|
|
|
-
|
|
|
- }];
|
|
|
- if (room) {
|
|
|
- strongSelf.room = room;
|
|
|
- strongSelf.room.delegate = self;
|
|
|
- }
|
|
|
-
|
|
|
- [strongSelf countMemberCount];
|
|
|
-
|
|
|
-
|
|
|
- if (room.remoteUsers.count) {
|
|
|
- NSMutableArray *streamArray = [NSMutableArray array];
|
|
|
- NSMutableArray *remoteUserArray = [room.remoteUsers mutableCopy];
|
|
|
- for (RCRTCRemoteUser *user in remoteUserArray) {
|
|
|
- if ([user.userId isEqualToString:strongSelf.createrId]) {
|
|
|
- strongSelf.isCreaterInRoom = YES;
|
|
|
- }
|
|
|
- if (user.remoteStreams.count) {
|
|
|
- [streamArray addObjectsFromArray:user.remoteStreams];
|
|
|
- [strongSelf subscribeRemoteResource:streamArray];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- [self changeEmptyStatusView];
|
|
|
- }
|
|
|
- });
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)closeAlertView {
|
|
|
- if (self.alertView && self.alertView.isShow) {
|
|
|
- [self.alertView removeFromSuperview];
|
|
|
- self.alertView = nil;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)displayCloseView {
|
|
|
- self.isCloseRoom = YES;
|
|
|
- [self hideTipsView];
|
|
|
- // 移除连麦视图
|
|
|
- [self clearRemoteContainer];
|
|
|
- if (self.micStatus != MICSTATUS_NOMAL) {
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
- self.liveRoleType = RCRTCLiveRoleTypeAudience;
|
|
|
- [self.engine.defaultAudioStream setMicrophoneDisable:YES];
|
|
|
- }
|
|
|
- [self.engine leaveRoom:^(BOOL isSuccess, RCRTCCode code) {
|
|
|
- if (code != RCRTCCodeSuccess) {
|
|
|
- // 退出失败
|
|
|
- }
|
|
|
- }];
|
|
|
- self.endView.hidden = NO;
|
|
|
- [self setDefaultBottomViewStatus];
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] postNotificationName:@"LiveroomClose" object:nil];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)insertMessage:(RCMessage *)rcMessage userInfo:(NSDictionary *)userInfo {
|
|
|
- // left
|
|
|
- NSDictionary *leftDic = userInfo;
|
|
|
- if (leftDic && [leftDic[@"left"] isEqual:@(0)]) {
|
|
|
- self.isNeedScrollToButtom = YES;
|
|
|
- }
|
|
|
- [self appendAndDisplayMessage:rcMessage];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)kickSeatWithMessage:(NSString *)message {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:message];
|
|
|
- self.micStatus = MICSTATUS_NOMAL;
|
|
|
- [self connectHostWithStatus:NO];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)showInviteAlertMessage:(NSString *)tipsMessage {
|
|
|
- if (self.alertView && self.alertView.isShow) {
|
|
|
- [self.alertView removeFromSuperview];
|
|
|
- self.alertView = nil;
|
|
|
- }
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [LiveRoomAlertView liveroomAlertWithTitle:tipsMessage leftButtonTitle:@"取消" rightTitle:@"确定" inView:self.view cancel:^{
|
|
|
- weakSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- [weakSelf sendSeatResponseMessage:NO];
|
|
|
- } confirm:^{
|
|
|
- [weakSelf sendSeatResponseMessage:YES];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)sendSeatResponseMessage:(BOOL)isApprove {
|
|
|
- SEATRESPONSE type = isApprove ? SEATRESPONSE_AUDIENCEAPPROVE : SEATRESPONSE_AUDIENCEREJECT;
|
|
|
- KSLiveChatroomSeatResponse *responseMessage = [[KSLiveChatroomSeatResponse alloc] init];
|
|
|
- responseMessage.type = type;
|
|
|
- responseMessage.audienceId = UserDefault(IM_USERID);
|
|
|
- responseMessage.audienceName = UserDefault(NicknameKey);
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:responseMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- if (success) {
|
|
|
- if (isApprove) {
|
|
|
- [weakSelf connectHostWithStatus:YES];
|
|
|
- }
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showEmptyViewDisplay:(BOOL)isPublish {
|
|
|
- NSString *imageName = @"";
|
|
|
- NSString *descMessage = @"";
|
|
|
- if (isPublish) {
|
|
|
- imageName = @"liveVideo_close";
|
|
|
- descMessage = @"老师已关闭画面!";
|
|
|
- }
|
|
|
- else {
|
|
|
- imageName = @"liveroom_empty";
|
|
|
- descMessage = @"休息一下,马上回来!";
|
|
|
- }
|
|
|
- [self.emptyView configViewWithImageName:imageName desc:descMessage];
|
|
|
- self.emptyView.hidden = NO;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)exitRoom {
|
|
|
- [self.engine.defaultAudioStream setMicrophoneDisable:YES];
|
|
|
- __weak typeof(self) weakSelf = self;
|
|
|
- [self.engine leaveRoom:^(BOOL isSuccess, RCRTCCode code) {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
- [strongSelf sendLeaveMessageCallback:^(BOOL success) {
|
|
|
- // quit 接口
|
|
|
- [weakSelf quitNotiferService];
|
|
|
- [weakSelf quitChatRoom];
|
|
|
- }];
|
|
|
- });
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-// 取消订阅流 Id 所对应的 View
|
|
|
-- (void)unsubscribeRemoteResource:(NSArray<RCRTCInputStream *> *)streams orStreamId:(NSString *)streamId {
|
|
|
-
|
|
|
- for (RCRTCInputStream *stream in streams) {
|
|
|
- if (stream.mediaType == RTCMediaTypeVideo) {
|
|
|
- streamId = stream.streamId;
|
|
|
- if ([stream.userId isEqualToString:self.createrId]) {
|
|
|
- [self clearVideoViewSource];
|
|
|
- self.isCreaterVideoEnable = NO;
|
|
|
- // 主讲老师停止发布视频流
|
|
|
- NSLog(@"----- 停止发布视频流");
|
|
|
- }
|
|
|
- [self fetchStreamVideoOffLineWithStreamId:streamId];
|
|
|
- }
|
|
|
- else if (stream.mediaType == RTCMediaTypeAudio && [stream.userId isEqualToString:self.createrId]) {
|
|
|
- // 主讲老师停止发布音频流
|
|
|
- NSLog(@"----- 停止发布音频流");
|
|
|
- self.isCreaterAudioEnable = NO;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark -- 加入直播间和退出直播间回到服务
|
|
|
-- (void)notiferJoinSuccessToServiceCallback:(void(^)(void))callback {
|
|
|
- callback();
|
|
|
- [KSNetworkingManager liveRoomJoinRoomRequest:KS_GET roomUid:self.roomId success:^(NSDictionary * _Nonnull dic) {
|
|
|
- callback();
|
|
|
- } faliure:^(NSError * _Nonnull error) {
|
|
|
- callback();
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark -- 退出直播间回掉服务
|
|
|
-- (void)quitNotiferService {
|
|
|
-
|
|
|
- [KSNetworkingManager LiveroomQuit:KS_POST success:^(NSDictionary * _Nonnull dic) {
|
|
|
- if ([dic ks_integerValueForKey:@"errCode"] == 0) {
|
|
|
- NSLog(@"success");
|
|
|
- }
|
|
|
- else {
|
|
|
- NSLog(@"----- error %@", [dic ks_stringValueForKey:@"errMsg"]);
|
|
|
- }
|
|
|
- } faliure:^(NSError * _Nonnull error) {
|
|
|
-
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)sendLeaveMessageCallback:(void(^)(BOOL success))callback {
|
|
|
-
|
|
|
- RCUserInfo *currentUserInfo = [RCIM sharedRCIM].currentUserInfo;
|
|
|
- KSLiveChatroomLeave *leaveMessage = [[KSLiveChatroomLeave alloc] init];
|
|
|
- leaveMessage.userId = currentUserInfo.userId;
|
|
|
- leaveMessage.userName = currentUserInfo.name;
|
|
|
- [self sendMessage:leaveMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
- callback(success);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)quitChatRoom {
|
|
|
- [[RCIMClient sharedRCIMClient] quitChatRoom:self.roomId success:^{
|
|
|
- NSLog(@"sucess log out--");
|
|
|
- } error:^(RCErrorCode status) {
|
|
|
- NSLog(@"RCErrorCode------%ld ", (long)status);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)addConstMessage { // 固定欢迎词语
|
|
|
- RCTextMessage *statement = [RCTextMessage messageWithContent:@"欢迎进入直播课堂,请遵守相关法规,禁止传播低俗、暴力等不良信息。为孩子创造健康绿色的学习环境。"];
|
|
|
- statement.extra = @"statement";
|
|
|
- RCMessage *constMessage = [[RCMessage alloc] initWithType:ConversationType_CHATROOM targetId:self.roomId direction:MessageDirection_SEND content:statement];
|
|
|
- constMessage.content.senderUserInfo = [RCIM sharedRCIM].currentUserInfo;
|
|
|
- [self appendAndDisplayMessage:constMessage];
|
|
|
-}
|
|
|
-#pragma mark - views init
|
|
|
-/**
|
|
|
- * 接收到消息的回调
|
|
|
- */
|
|
|
-- (void)didReceiveMessageNotification:(NSNotification *)notification {
|
|
|
- NSDictionary *dic = notification.object;
|
|
|
- __block RCMessage *rcMessage = dic[@"message"];
|
|
|
- KSRCMessageModel *model = [[KSRCMessageModel alloc] initWithMessage:rcMessage];
|
|
|
- model.userInfo = rcMessage.content.senderUserInfo;
|
|
|
- if (model.conversationType == ConversationType_CHATROOM && [model.targetId isEqualToString:self.roomId]) {
|
|
|
- __weak typeof(&*self) __blockSelf = self;
|
|
|
- dispatch_main_async_safe((^{
|
|
|
- // 对赞消息拦截 ,展示动画,不插入数据源 ,对于seat消息 和踢出消息,弹出alert
|
|
|
- if (rcMessage) {
|
|
|
- // 👍🏻消息
|
|
|
- if ([rcMessage.content isMemberOfClass:[KSLiveChatroomLike class]]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[RCChatroomLikeCount class]]) {
|
|
|
- RCChatroomLikeCount *likeCountMessage = (RCChatroomLikeCount *)rcMessage.content;
|
|
|
- __blockSelf.likeCount = likeCountMessage.count;
|
|
|
- [__blockSelf countLikeMessageCount];
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomWelcome class]]) {
|
|
|
- // 过滤自己发送的欢迎消息
|
|
|
- if ([rcMessage.senderUserId isEqualToString:UserDefault(IM_USERID)]) {
|
|
|
- return;
|
|
|
- }
|
|
|
-// if ([rcMessage.senderUserId isEqual:self.createrId]) { // 如果是老师 重置连麦申请状态
|
|
|
-// [__blockSelf resetMicWaitToNomal];
|
|
|
-// }
|
|
|
-
|
|
|
- RCUserInfo *userInfo = rcMessage.content.senderUserInfo;
|
|
|
- NSString *userName = [userInfo.name stringByAppendingString:@""];
|
|
|
- NSString *contentMsg = [NSString stringWithFormat:@"%@ 进入直播间",userName];
|
|
|
- [__blockSelf showAnimationView:YES showMessag:contentMsg];
|
|
|
- }
|
|
|
- // 用户退出消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomLeave class]]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // 用户退出消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomUserQuit class]]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomKickOut class]]) {
|
|
|
- KSLiveChatroomKickOut *kickMessage = (KSLiveChatroomKickOut *)rcMessage.content;
|
|
|
- NSString *currentUserId = UserDefault(IM_USERID);
|
|
|
- if ([kickMessage.targetId isEqualToString:currentUserId]) {
|
|
|
- __blockSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- [__blockSelf kickOutLiveRoom];
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- // 人数同步
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomMemberUp class]]) {
|
|
|
- KSLiveChatroomMemberUp *member = (KSLiveChatroomMemberUp *)rcMessage.content;
|
|
|
- __blockSelf.totalCount = member.count;
|
|
|
- [__blockSelf countMemberCount];
|
|
|
- return;
|
|
|
- }
|
|
|
- // 连麦控制消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[RCChatroomSeatsControl class]]) {
|
|
|
- RCChatroomSeatsControl *seatControlMessage = (RCChatroomSeatsControl *)rcMessage.content;
|
|
|
- if (seatControlMessage.seatBan) { // 禁止连麦
|
|
|
- __blockSelf.enableSeat = NO;
|
|
|
-
|
|
|
- // 未连麦情况下才重置
|
|
|
- if (__blockSelf.micStatus != MICSTATUS_CONNECTING) {
|
|
|
- __blockSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- }
|
|
|
-
|
|
|
- [__blockSelf hideApplyView];
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- }
|
|
|
- else { // 开启连麦
|
|
|
- __blockSelf.enableSeat = YES;
|
|
|
- }
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- // 连麦申请消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomSeatApply class]]) {
|
|
|
- KSLiveChatroomSeatApply *seatApplyMessage = (KSLiveChatroomSeatApply *)rcMessage.content;
|
|
|
- // 只处理和自己相关的消息
|
|
|
- if (![seatApplyMessage.audienceId isEqualToString:UserDefault(IM_USERID)]) {
|
|
|
- // 刷新麦序
|
|
|
- return;
|
|
|
- }
|
|
|
- if (seatApplyMessage.type == SEATHANDLE_INVITE) { // 老师发起申请
|
|
|
- NSString *titles = [NSString stringWithFormat:@"%@邀请您连麦",[NSString returnNoNullStringWithString:seatApplyMessage.teacherName]];
|
|
|
- [__blockSelf showInviteAlertMessage:titles];
|
|
|
- }
|
|
|
- else if (seatApplyMessage.type == SEATHANDLE_DISINVITE) { // 老师撤回邀请
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师撤回了连麦邀请"];
|
|
|
- if (__blockSelf.alertView && __blockSelf.alertView.isShow) {
|
|
|
- [__blockSelf.alertView dismissAlertView];
|
|
|
- }
|
|
|
- }
|
|
|
- else if (seatApplyMessage.type == SEATHANDLE_KICKSEAT) { // 老师将麦上观众抱下麦
|
|
|
- [__blockSelf kickSeatWithMessage:@"您已被抱下麦"];
|
|
|
- }
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- // 连麦回复消息(暂不处理)
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomSeatResponse class]]) {
|
|
|
- KSLiveChatroomSeatResponse *seatResponseMessage = (KSLiveChatroomSeatResponse *)rcMessage.content;
|
|
|
- if (![seatResponseMessage.audienceId isEqualToString:UserDefault(IM_USERID)]) { // 只处理和自己相关的消息
|
|
|
- return;
|
|
|
- }
|
|
|
- if (seatResponseMessage.type == SEATRESPONSE_TEACHERAPPROVE && __blockSelf.micStatus == MICSTATUS_WAITING) { //
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- [__blockSelf connectHostWithStatus:YES];
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- else if (seatResponseMessage.type == SEATRESPONSE_TEACHERREJECT) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师拒绝了您的连麦申请"];
|
|
|
- __blockSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomDownSeat class]]) { // 成员下麦消息
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomDownSeat class]]) { // 成员主动下麦消息
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomClose class]]) { // 直播间已关闭
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"直播已结束"];
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- // 显示直播间关闭状态
|
|
|
- [__blockSelf closeAlertView];
|
|
|
- [__blockSelf displayCloseView];
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- });
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[RCTextMessage class]]) {
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSRCPauseLiveMessage class]]) { // 老师暂停直播
|
|
|
- __blockSelf.isPauseLive = YES;
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师已暂停直播"];
|
|
|
- if (__blockSelf.micStatus == MICSTATUS_WAITING) {
|
|
|
- [__blockSelf sendSeatMessageApply:NO];
|
|
|
- }
|
|
|
- [__blockSelf resetConnectionStatus];
|
|
|
- [__blockSelf resetNetTips];
|
|
|
- [__blockSelf closeAlertView];
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- return;
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSRCShopRushMessage class]]) { //
|
|
|
-
|
|
|
- KSRCShopRushMessage *rushMsg = (KSRCShopRushMessage *)rcMessage.content;
|
|
|
-
|
|
|
- NSString *contentMsg = [NSString stringWithFormat:@"%@ 正在抢购",[NSString returnNoNullStringWithString:rushMsg.userName]];
|
|
|
- [__blockSelf showAnimationView:NO showMessag:contentMsg];
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveBlockUser class]]) { // 黑名单
|
|
|
- KSLiveBlockUser *blockMessage = (KSLiveBlockUser *)rcMessage.content;
|
|
|
- if ([blockMessage.userId isEqualToString:UserDefault(IM_USERID)]) {
|
|
|
- __blockSelf.blacklistFlag = YES;
|
|
|
- [__blockSelf resetConnectionStatus];
|
|
|
- }
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveUnBlockUser class]]) {
|
|
|
- KSLiveUnBlockUser *unBlockMessage = (KSLiveUnBlockUser *)rcMessage.content;
|
|
|
- if ([unBlockMessage.userId isEqualToString:UserDefault(IM_USERID)]) {
|
|
|
- __blockSelf.blacklistFlag = NO;
|
|
|
- }
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSDownSeatAllMessage class]]) { // 所有麦上用户下麦
|
|
|
- if (__blockSelf.micStatus == MICSTATUS_CONNECTING) {
|
|
|
- [__blockSelf kickSeatWithMessage:@"您已被抱下麦"];
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- }
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSRejectAllSeatMessage class]]) { // 拒绝所有连麦申请
|
|
|
- if (__blockSelf.micStatus == MICSTATUS_WAITING) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师拒绝了您的连麦申请"];
|
|
|
- // 处理连麦状态
|
|
|
- __blockSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- [__blockSelf insertMessage:rcMessage userInfo:notification.userInfo];
|
|
|
- [__blockSelf hideApplyingView];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }));
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)hideApplyView {
|
|
|
- if (self.applyView.isShow) {
|
|
|
- [self.applyView hideView];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)hideApplyingView {
|
|
|
- if (self.applyingView.isShow) {
|
|
|
- [self.applyingView hideView];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// 发送人数同步消息
|
|
|
-- (void)sendMemberCountMessage {
|
|
|
- KSLiveChatroomMemberCount *syncMessage = [[KSLiveChatroomMemberCount alloc] init];
|
|
|
- syncMessage.count = self.totalCount;
|
|
|
-
|
|
|
- [self sendMessage:syncMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
-
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark ----- time manager delegate
|
|
|
-- (void)quitClassroomNotifer {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"直播课已结束!"];
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitAction];
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark - gesture and button action
|
|
|
-- (void)resetBottomGesture:(UIGestureRecognizer *)gestureRecognizer {
|
|
|
- if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
|
|
|
- [self setDefaultBottomViewStatus];
|
|
|
- }
|
|
|
-}
|
|
|
-- (void)setDefaultBottomViewStatus {
|
|
|
- [self.inputBar setInputBarStatus:KSBottomBarStatusDefault];
|
|
|
- [self.inputBar setHidden:YES];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#pragma mark ---- sendMessage/showMessage
|
|
|
-- (void)sendMessage:(RCMessageContent *)messageContent displayMessage:(BOOL)displayMessage callback:(void(^)(BOOL success))callback {
|
|
|
- if (_roomId == nil) {
|
|
|
- return;
|
|
|
- }
|
|
|
- messageContent.senderUserInfo = [RCIM sharedRCIM].currentUserInfo;
|
|
|
- if (messageContent == nil) {
|
|
|
- return;
|
|
|
- }
|
|
|
- __weak typeof(&*self) __weakself = self;
|
|
|
- [KSChatroomMessageCenter sendChatMessage:self.roomId content:messageContent success:^(long messageId) {
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- RCMessage *message = [[RCMessage alloc] initWithType:ConversationType_CHATROOM targetId:__weakself.roomId direction:MessageDirection_SEND content:messageContent];
|
|
|
- message.content.senderUserInfo = [RCIM sharedRCIM].currentUserInfo;
|
|
|
-
|
|
|
- message.senderUserId = UserDefault(IM_USERID);
|
|
|
- if (displayMessage) {
|
|
|
- [__weakself appendAndDisplayMessage:message];
|
|
|
- }
|
|
|
- [__weakself.inputBar clearInputView];
|
|
|
- callback(YES);
|
|
|
- });
|
|
|
-
|
|
|
- } error:^(RCErrorCode errorCode, long messageId) {
|
|
|
- if (errorCode == RC_CHATROOM_NOT_EXIST) {
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"聊天已被解散,请退出后重进。"];
|
|
|
- });
|
|
|
- }
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- [__weakself.inputBar clearInputView];
|
|
|
- NSLog(@"发送失败,errorcode is: %ld",(long)errorCode);
|
|
|
- callback(NO);
|
|
|
- });
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 将消息加入本地数组
|
|
|
- */
|
|
|
-- (void)appendAndDisplayMessage:(RCMessage *)rcMessage {
|
|
|
- if (!rcMessage) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- KSRCMessageModel *model = [[KSRCMessageModel alloc] initWithMessage:rcMessage];
|
|
|
- model.userInfo = rcMessage.content.senderUserInfo;
|
|
|
- if (!model.userInfo) {
|
|
|
- model.userInfo = [RCIMClient sharedRCIMClient].currentUserInfo;
|
|
|
- }
|
|
|
-
|
|
|
- if ([self appendMessageModel:model]) {
|
|
|
- NSIndexPath *indexPath =
|
|
|
- [NSIndexPath indexPathForItem:self.conversationDataRepository.count - 1
|
|
|
- inSection:0];
|
|
|
- if ([self.conversationMessageTableView numberOfRowsInSection:0] !=
|
|
|
- self.conversationDataRepository.count - 1) {
|
|
|
- return;
|
|
|
- }
|
|
|
- // view刷新
|
|
|
- [self.conversationMessageTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
|
|
|
- if ([self isAtTheBottomOfTableView] || self.isNeedScrollToButtom) {
|
|
|
- [self scrollToBottomAnimated:YES];
|
|
|
- self.isNeedScrollToButtom=NO;
|
|
|
- }
|
|
|
- }
|
|
|
- return;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 如果当前会话没有这个消息id,把消息加入本地数组
|
|
|
- */
|
|
|
-- (BOOL)appendMessageModel:(KSRCMessageModel *)model {
|
|
|
-
|
|
|
- if (!model.content) {
|
|
|
- return NO;
|
|
|
- }
|
|
|
- //这里可以根据消息类型来决定是否显示,如果不希望显示直接return NO
|
|
|
-
|
|
|
- //数量不可能无限制的大,这里限制收到消息过多时,就对显示消息数量进行限制。
|
|
|
- //用户可以手动下拉更多消息,查看更多历史消息。
|
|
|
- if (self.conversationDataRepository.count>500) {
|
|
|
- // NSRange range = NSMakeRange(0, 1);
|
|
|
- KSRCMessageModel *message = self.conversationDataRepository[0];
|
|
|
- [[RCIMClient sharedRCIMClient]deleteMessages:@[@(message.messageId)]];
|
|
|
- [self.conversationDataRepository removeObjectAtIndex:0];
|
|
|
- [self.conversationMessageTableView reloadData];
|
|
|
- }
|
|
|
-
|
|
|
- [self.conversationDataRepository addObject:model];
|
|
|
- return YES;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 判断消息是否在collectionView的底部
|
|
|
- *
|
|
|
- * @return 是否在底部
|
|
|
- */
|
|
|
-- (BOOL)isAtTheBottomOfTableView {
|
|
|
- if (self.conversationMessageTableView.contentSize.height <= self.conversationMessageTableView.frame.size.height) {
|
|
|
- return YES;
|
|
|
- }
|
|
|
- if(self.conversationMessageTableView.contentOffset.y +200 >= (self.conversationMessageTableView.contentSize.height - self.conversationMessageTableView.frame.size.height)) {
|
|
|
- return YES;
|
|
|
- }else{
|
|
|
- return NO;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * 消息滚动到底部
|
|
|
- *
|
|
|
- * @param animated 是否开启动画效果
|
|
|
- */
|
|
|
-- (void)scrollToBottomAnimated:(BOOL)animated {
|
|
|
- if ([self.conversationMessageTableView numberOfSections] == 0) {
|
|
|
- return;
|
|
|
- }
|
|
|
- NSUInteger finalRow = MAX(0, [self.conversationMessageTableView numberOfRowsInSection:0] - 1);
|
|
|
- if (0 == finalRow) {
|
|
|
- return;
|
|
|
- }
|
|
|
- NSIndexPath *finalIndexPath =
|
|
|
- [NSIndexPath indexPathForItem:finalRow inSection:0];
|
|
|
- [self.conversationMessageTableView scrollToRowAtIndexPath:finalIndexPath atScrollPosition:UITableViewScrollPositionTop animated:animated];
|
|
|
-}
|
|
|
-/*
|
|
|
-#pragma mark - Navigation
|
|
|
-
|
|
|
-// In a storyboard-based application, you will often want to do a little preparation before navigation
|
|
|
-- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
|
|
- // Get the new view controller using [segue destinationViewController].
|
|
|
- // Pass the selected object to the new view controller.
|
|
|
-}
|
|
|
-*/
|
|
|
-
|
|
|
-#pragma mark ----- table data source
|
|
|
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
|
|
- return self.conversationDataRepository.count;
|
|
|
-}
|
|
|
-
|
|
|
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
- KSRCMessageModel *model = [self.conversationDataRepository objectAtIndex:indexPath.row];
|
|
|
- RCMessageContent *messageContent = model.content;
|
|
|
- KSChatroomTextCell *cell = [tableView dequeueReusableCellWithIdentifier:@"KSChatroomTextCell"];
|
|
|
- if(!cell){
|
|
|
- cell = [[KSChatroomTextCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"KSChatroomTextCell"];
|
|
|
- }
|
|
|
- if ([messageContent isMemberOfClass:[RCTextMessage class]] || [messageContent isMemberOfClass:[KSLiveChatroomWelcome class]] || [messageContent isMemberOfClass:[KSLiveChatroomLike class]] || [messageContent isMemberOfClass:[KSLiveChatroomSeatApply class]] || [messageContent isMemberOfClass:[KSLiveChatroomSeatResponse class]] || [messageContent isMemberOfClass:[KSDownSeatAllMessage class]] || [messageContent isMemberOfClass:[KSRejectAllSeatMessage class]] || [messageContent isMemberOfClass:[RCChatroomSeatsControl class]]){
|
|
|
- [cell setDataModel:model createrId:self.createrId];
|
|
|
- }
|
|
|
- return cell;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)sendSeatMessageApply:(BOOL)isApply {
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已上麦"];
|
|
|
- return;
|
|
|
- }
|
|
|
- SEATHANDLE type = isApply ? SEATHANDLE_APPLY : SEATHANDLE_CANCELAPPLY;
|
|
|
- KSLiveChatroomSeatApply *applyMessage = [[KSLiveChatroomSeatApply alloc] init];
|
|
|
- applyMessage.type = type;
|
|
|
- applyMessage.audienceId = UserDefault(IM_USERID);
|
|
|
- applyMessage.audienceName = UserDefault(NicknameKey);
|
|
|
- applyMessage.audienceAvatar = UserDefault(AvatarUrlKey);
|
|
|
- applyMessage.teacherId = self.createrId;
|
|
|
- applyMessage.teacherName = self.createrName;
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:applyMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- if (success) {
|
|
|
- weakSelf.micStatus = isApply ? MICSTATUS_WAITING : MICSTATUS_NOMAL;
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- 点赞
|
|
|
- */
|
|
|
-- (void)praiseBtnPressed {
|
|
|
- NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
|
|
|
- __weak __typeof(&*self)weakSelf = self;
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.21 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- if ([[NSDate date] timeIntervalSince1970] - self.lastClickPraiseTime >= 0.2) {
|
|
|
-
|
|
|
- KSLiveChatroomLike *praiseSendMessage = [[KSLiveChatroomLike alloc] init];
|
|
|
- praiseSendMessage.counts = clickPraiseBtnTimes;
|
|
|
- [weakSelf sendMessage:praiseSendMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
-
|
|
|
- }];
|
|
|
- clickPraiseBtnTimes = 0;
|
|
|
-
|
|
|
-// self.likeCount += praiseSendMessage.counts;
|
|
|
-// [self countLikeMessageCount];
|
|
|
- }
|
|
|
- });
|
|
|
- KSLiveChatroomLike *praiseMessage = [[KSLiveChatroomLike alloc] init];
|
|
|
- clickPraiseBtnTimes++;
|
|
|
- self.lastClickPraiseTime = currentTime;
|
|
|
- [self presentLikeMessageAnimation:praiseMessage];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- 赞动画
|
|
|
-
|
|
|
- @param likeMessage 赞消息
|
|
|
- */
|
|
|
-- (void)presentLikeMessageAnimation:(KSLiveChatroomLike *)likeMessage {
|
|
|
- LiveRoomLikeLayer *layer = [[LiveRoomLikeLayer alloc] initWithName:@"Like"];
|
|
|
- [self.view.layer addSublayer:layer];
|
|
|
- CGRect tempFrame = [self.view convertRect:self.bottomView.likeButton.frame fromView:self.bottomView];
|
|
|
- CGFloat width = tempFrame.size.width;
|
|
|
- CGFloat height = tempFrame.size.height;
|
|
|
-
|
|
|
- CGFloat dx = CGRectGetMidX(tempFrame) - width *0.5;
|
|
|
- CGFloat dy = CGRectGetMidY(tempFrame) - 8 - height;
|
|
|
- layer.frame = CGRectMake(dx, dy, width, height);
|
|
|
- [layer startAnimation];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#pragma mark - setter & getter
|
|
|
-- (void)setMicStatus:(MICSTATUS)micStatus {
|
|
|
- _micStatus = micStatus;
|
|
|
- if (self.bottomView) {
|
|
|
- switch (micStatus) {
|
|
|
- case MICSTATUS_NOMAL:
|
|
|
- {
|
|
|
- [self.bottomView.seatButton setImage:[UIImage imageNamed:@"seat_nomal"] forState:UIControlStateNormal];
|
|
|
- }
|
|
|
- break;
|
|
|
- case MICSTATUS_WAITING:
|
|
|
- {
|
|
|
- [self.bottomView.seatButton setImage:[UIImage imageNamed:@"seating_image"] forState:UIControlStateNormal];
|
|
|
- }
|
|
|
- break;
|
|
|
- case MICSTATUS_CONNECTING:
|
|
|
- {
|
|
|
- [self.bottomView.seatButton setImage:[UIImage imageNamed:@"seat_image"] forState:UIControlStateNormal];
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark ----- RCRTCEngineEventDelegate
|
|
|
-- (void)didRTCConnectionStateChanged:(RCRTCConnectionState)state {
|
|
|
- if (state == RCRTCConnectionStateConnecting) {
|
|
|
- NSLog(@"--------RCRTCConnectionStateConnecting");
|
|
|
- }
|
|
|
- else if (state == RCRTCConnectionStateConnected) {
|
|
|
- NSLog(@"--------RCRTCConnectionStateConnected");
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark ----- RCRTCStatusReportDelegate
|
|
|
-- (void)didReportStatusForm:(RCRTCStatusForm *)form {
|
|
|
- // 获取丢包率
|
|
|
-
|
|
|
- for (RCRTCStreamStat *stat in form.recvStats) {
|
|
|
-
|
|
|
- if ([stat.mediaType isEqualToString:@"video"]) { // 接收视频会出现视频黑的情况 bitRate = 0
|
|
|
- if (stat.packetLoss >= PACKAGE_LOST) { // 丢包
|
|
|
- if (self.lostStartTime == 0) { // 如果之前没有丢包
|
|
|
- self.lostStartTime = [[NSDate date] timeIntervalSince1970];
|
|
|
- }
|
|
|
- else {
|
|
|
- NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
|
|
|
- if (currentTime - self.lostStartTime >= 8) {
|
|
|
- self.isLostPackage = YES;
|
|
|
- [self showBadNetTips];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- self.lostStartTime = 0;
|
|
|
- self.isLostPackage = NO;
|
|
|
- [self hideTipsView];
|
|
|
- }
|
|
|
-
|
|
|
- if (stat.bitRate == 0) {
|
|
|
- if (self.bitErrorTime == 0) {
|
|
|
- self.bitErrorTime = [[NSDate date] timeIntervalSince1970];
|
|
|
- }
|
|
|
- else {
|
|
|
- NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
|
|
|
- if (currentTime - self.bitErrorTime >= 5) {
|
|
|
- self.isBitError = YES;
|
|
|
- [self showBadNetTips];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- self.isBitError = NO;
|
|
|
- self.bitErrorTime = 0;
|
|
|
- [self hideTipsView];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-// NSLog(@"%@",form.description);
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showBadNetTips {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- if (self.isCloseRoom == NO) {
|
|
|
- if (self.netBadView.hidden == YES) {
|
|
|
- self.netBadView.hidden = NO;
|
|
|
- self.videoView.hidden = YES;
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-- (void)hideTipsView {
|
|
|
- dispatch_main_async_safe(^{
|
|
|
- if (self.netBadView.hidden == NO) {
|
|
|
- if (self.isBitError == NO && self.isLostPackage == NO) {
|
|
|
- self.netBadView.hidden = YES;
|
|
|
- self.videoView.hidden = NO;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- })
|
|
|
-
|
|
|
-}
|
|
|
-#pragma mark --- lazying
|
|
|
-
|
|
|
-- (KSChatVideoView *)videoView {
|
|
|
- if (!_videoView) {
|
|
|
- _videoView = [[KSChatVideoView alloc] initWithFrame:self.view.bounds];
|
|
|
- _videoView.backgroundColor = [UIColor clearColor];
|
|
|
- }
|
|
|
- return _videoView;
|
|
|
-}
|
|
|
-
|
|
|
-- (UIView *)videoContainerView {
|
|
|
- if (!_videoContainerView) {
|
|
|
- _videoContainerView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
|
- _videoContainerView.backgroundColor = [UIColor clearColor];
|
|
|
- }
|
|
|
- return _videoContainerView;
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveRoomHeadView *)headView {
|
|
|
- if (!_headView) {
|
|
|
- _headView = [LiveRoomHeadView shareInstance];
|
|
|
- MJWeakSelf;
|
|
|
- [_headView quitAction:^{
|
|
|
- [weakSelf showQuitAlert];
|
|
|
-
|
|
|
- }];
|
|
|
-// [_headView quitAction:^(BOOL isQuit) {
|
|
|
-// if (isQuit) {
|
|
|
-// [weakSelf showQuitAlert];
|
|
|
-// }
|
|
|
-// else {
|
|
|
-// [weakSelf displayTeacherInfo:CART_TYPE_NONE];
|
|
|
-// }
|
|
|
-// }];
|
|
|
-
|
|
|
- }
|
|
|
- return _headView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showTeacherCenter {
|
|
|
-
|
|
|
-}
|
|
|
-- (void)showQuitAlert {
|
|
|
- if (self.isCloseRoom) { // 如果直播结束 直接点击退出房间
|
|
|
- [self quitRoom];
|
|
|
- }
|
|
|
- else if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
|
- [self quitAction];
|
|
|
- }
|
|
|
- else {
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [LiveRoomAlertView liveroomAlertWithTitle:@"是否退出直播间" leftButtonTitle:@"取消" rightTitle:@"退出" inView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [weakSelf quitAction];
|
|
|
- }];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (LiveRoomBottomView *)bottomView {
|
|
|
- if (!_bottomView) {
|
|
|
- _bottomView = [LiveRoomBottomView shareInstance];
|
|
|
- MJWeakSelf;
|
|
|
- [_bottomView bottomClickAction:^(LIVEROOMACTION action) {
|
|
|
- [weakSelf bottomViewAction:action];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _bottomView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)bottomViewAction:(LIVEROOMACTION)action {
|
|
|
- if (self.isCloseRoom) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"直播已结束"];
|
|
|
- return;
|
|
|
- }
|
|
|
- switch (action) {
|
|
|
- case LIVEROOMACTION_CHAT: // 聊天
|
|
|
- {
|
|
|
- if (self.blacklistFlag == YES) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已被老师禁言"];
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- [_inputBar setHidden:NO];
|
|
|
- [_inputBar setInputBarStatus:KSBottomBarStatusKeyboard];
|
|
|
-
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVEROOMACTION_SEAT: // // 连麦按钮
|
|
|
- { // 连麦按钮
|
|
|
- // 判断是否是连麦状态
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING) { // 连麦中
|
|
|
- // 是否取消连麦
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [LiveRoomAlertView liveroomAlertWithTitle:@"连麦中,确认取消连麦吗?" leftButtonTitle:@"取消" rightTitle:@"确定" inView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [weakSelf connectHostWithStatus:NO];
|
|
|
- }];
|
|
|
-
|
|
|
- }
|
|
|
- else if (self.micStatus == MICSTATUS_WAITING) { // 连麦申请中
|
|
|
- // 弹窗取消申请
|
|
|
- [self displayApplyingView];
|
|
|
- }
|
|
|
- else {
|
|
|
- if (self.blacklistFlag == YES) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已被老师禁言"];
|
|
|
- return;
|
|
|
- }
|
|
|
- if (self.isCreaterInRoom == NO) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师不在直播间"];
|
|
|
- return;
|
|
|
- }
|
|
|
- if (self.isPauseLive == YES) {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师暂停中,暂时无法接受邀请"];
|
|
|
- return;
|
|
|
- }
|
|
|
- if (self.enableSeat) {
|
|
|
- // 显示弹窗
|
|
|
- [self displaySeatApplyView];
|
|
|
- }
|
|
|
- else {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师关闭连麦申请"];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVEROOMACTION_SHOP:
|
|
|
- {
|
|
|
- [self showCartAlert];
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVEROOMACTION_LIKE:
|
|
|
- {
|
|
|
- if (self.isCreaterInRoom) {
|
|
|
- [self praiseBtnPressed];
|
|
|
- }
|
|
|
- else {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"老师不在直播间"];
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
-// case LIVEROOMACTION_SHARE:
|
|
|
-// {
|
|
|
-// [self showShareAlert];
|
|
|
-// }
|
|
|
-// break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showShareAlert {
|
|
|
- NSString *qrUrl = [NSString stringWithFormat:@"%@%@?id=%@&userId=%@",WEBHOST,@"/#/shareLiveRoom",self.roomId,UserDefault(UIDKey)];
|
|
|
- self.shareView = [ShareLiveDisplayView shareInstance];
|
|
|
- [self.shareView configWithTeacherAvatar:self.createrAvatal teacherName:self.createrName qrUrl:qrUrl];
|
|
|
- MJWeakSelf;
|
|
|
- [self.shareView shareActionCallback:^(SHARETYPE type) {
|
|
|
- UIImage *image = [UIImage getCurrentViewShot:weakSelf.shareView.containerView];
|
|
|
- if (type == SHARETYPE_SAVE) {
|
|
|
- [weakSelf savePicWithImage:image];
|
|
|
- }
|
|
|
- else {
|
|
|
- [weakSelf showShareUI:image];
|
|
|
- }
|
|
|
- }];
|
|
|
- [self.shareView showShareViewInView:self.view];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)displaySeatApplyView {
|
|
|
- [self.applyView showInView:self.view];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)displayApplyingView {
|
|
|
- [self.applyingView showInView:self.view];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showCartAlert {
|
|
|
- [self.cardView showViewInView:self.view];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)quitAction {
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [LiveRoomAlertView liveroomAlertWithTitle:@"连麦中,是否退出房间?" leftButtonTitle:@"取消" rightTitle:@"确定" inView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [weakSelf quitRoom];
|
|
|
- }];
|
|
|
- }
|
|
|
- else {
|
|
|
- [self quitRoom];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)quitRoom {
|
|
|
- KSDragWindowManager *manager = [KSDragWindowManager sharedManager];
|
|
|
- if (manager.hasShowWindow) {
|
|
|
- [manager resignDragWindow];
|
|
|
- }
|
|
|
- // 清理视图
|
|
|
- [self clearRemoteContainer];
|
|
|
- // 退出房间
|
|
|
- [self exitRoom];
|
|
|
- [self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
|
|
-}
|
|
|
-
|
|
|
-- (RCRTCEngine *)engine {
|
|
|
- if (!_engine) {
|
|
|
- _engine = [RCRTCEngine sharedInstance];
|
|
|
- [_engine setStatusReportDelegate:self];
|
|
|
- [_engine setDelegate:self];
|
|
|
- }
|
|
|
- return _engine;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSMutableArray<KSLiveStreamVideo *> *)streamVideos {
|
|
|
- if (!_streamVideos) {
|
|
|
- _streamVideos = [NSMutableArray array];
|
|
|
- }
|
|
|
- return _streamVideos;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSLiveStreamVideo *)localVideo {
|
|
|
- if (!_localVideo) {
|
|
|
- _localVideo = [KSLiveStreamVideo LocalStreamVideo];
|
|
|
- }
|
|
|
- return _localVideo;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (UIView *)messageContentView {
|
|
|
- if (!_messageContentView) {
|
|
|
- _messageContentView = [[UIView alloc] init];
|
|
|
- [_messageContentView setBackgroundColor: [UIColor clearColor]];
|
|
|
- }
|
|
|
- return _messageContentView;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSMutableArray<KSRCMessageModel *> *)conversationDataRepository {
|
|
|
- if (!_conversationDataRepository) {
|
|
|
- _conversationDataRepository = [NSMutableArray array];
|
|
|
- }
|
|
|
- return _conversationDataRepository;
|
|
|
-}
|
|
|
-- (KSChatInputBarControl *)inputBar {
|
|
|
- if (!_inputBar) {
|
|
|
- _inputBar = [[KSChatInputBarControl alloc] initWithStatus:KSBottomBarStatusDefault];
|
|
|
- [_inputBar setDelegate:self];
|
|
|
- }
|
|
|
- return _inputBar;
|
|
|
-}
|
|
|
-
|
|
|
-- (UITableView *)conversationMessageTableView {
|
|
|
- if (!_conversationMessageTableView) {
|
|
|
- _conversationMessageTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
|
|
|
- _conversationMessageTableView.backgroundColor = [UIColor clearColor];
|
|
|
- _conversationMessageTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
|
|
- _conversationMessageTableView.dataSource = self;
|
|
|
- _conversationMessageTableView.delegate = self;
|
|
|
- _conversationMessageTableView.rowHeight = UITableViewAutomaticDimension;
|
|
|
- _conversationMessageTableView.estimatedRowHeight = 40.0f;
|
|
|
- _conversationMessageTableView.showsVerticalScrollIndicator = NO;
|
|
|
- [_conversationMessageTableView registerClass:[KSChatroomTextCell class] forCellReuseIdentifier:@"KSChatroomTextCell"];
|
|
|
- }
|
|
|
- return _conversationMessageTableView;
|
|
|
-}
|
|
|
-
|
|
|
-- (SeatContentView *)seatContainer {
|
|
|
- if (!_seatContainer) {
|
|
|
- _seatContainer = [[SeatContentView alloc] init];
|
|
|
- }
|
|
|
- return _seatContainer;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSLiveEmptyView *)emptyView {
|
|
|
- if (!_emptyView) {
|
|
|
- _emptyView = [[KSLiveEmptyView alloc] init];
|
|
|
- _emptyView.backgroundColor = [UIColor clearColor];
|
|
|
- BOOL isPhoneLive = YES;
|
|
|
- [_emptyView dispPlayViewIsPhoneLive:isPhoneLive];
|
|
|
- }
|
|
|
- return _emptyView;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSLiveEndView *)endView {
|
|
|
- if (!_endView) {
|
|
|
- _endView = [[KSLiveEndView alloc] init];
|
|
|
- _endView.backgroundColor = HexRGB(0x25292e);
|
|
|
- BOOL isPhoneLive = YES;
|
|
|
- [_endView dispPlayViewIsPhoneLive:isPhoneLive];
|
|
|
- }
|
|
|
- return _endView;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSLiveBadNetView *)netBadView {
|
|
|
- if (!_netBadView) {
|
|
|
- _netBadView = [[KSLiveBadNetView alloc] init];
|
|
|
- BOOL isPhoneLive = YES;
|
|
|
- [_netBadView dispPlayViewIsPhoneLive:isPhoneLive];
|
|
|
- MJWeakSelf;
|
|
|
- [_netBadView configViewWithImageName:@"liveVideo_close" desc:@"当前网络状态不佳" callback:^{
|
|
|
- [weakSelf resetAllConnection];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _netBadView;
|
|
|
-}
|
|
|
-
|
|
|
-- (LOTAnimationView *)animationView {
|
|
|
- if (!_animationView) {
|
|
|
- _animationView = [LOTAnimationView animationWithFilePath:[[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"LiveCard" ofType:@"bundle"]] pathForResource:@"cardAnimation" ofType:@"json"]];
|
|
|
- _animationView.loopAnimation = YES;
|
|
|
- }
|
|
|
- return _animationView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)resetNetTips {
|
|
|
- self.lostStartTime = 0;
|
|
|
- self.isBitError = NO;
|
|
|
- self.bitErrorTime = 0;
|
|
|
- self.isLostPackage = NO;
|
|
|
- [self hideTipsView];
|
|
|
-}
|
|
|
-
|
|
|
-// 黑名单
|
|
|
-- (void)setBlacklistFlag:(BOOL)blacklistFlag {
|
|
|
- _blacklistFlag = blacklistFlag;
|
|
|
- [self refreshBottomChatStatus];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)refreshBottomChatStatus {
|
|
|
- if (self.bottomView) {
|
|
|
- NSString *tipsTitle = self.blacklistFlag ? @"您已被老师禁言" : @"快来互动吧!";
|
|
|
- self.bottomView.tipsLabel.text = tipsTitle;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)resetAllConnection {
|
|
|
- [self resetNetTips];
|
|
|
- // 清理视图
|
|
|
- [self.streamVideos removeAllObjects];
|
|
|
- [self clearVideoViewSource];
|
|
|
- [self removeSeatContainer];
|
|
|
-
|
|
|
- // 立刻房间后重新加入房间
|
|
|
-
|
|
|
- // 退出房间
|
|
|
- [self.engine.defaultAudioStream setMicrophoneDisable:YES];
|
|
|
- __weak typeof(self) weakSelf = self;
|
|
|
-
|
|
|
- [self.engine leaveRoom:^(BOOL isSuccess, RCRTCCode code) {
|
|
|
- __strong typeof(weakSelf) strongSelf = weakSelf;
|
|
|
- if (code != RCRTCCodeSuccess) {
|
|
|
- // 退出失败
|
|
|
- }
|
|
|
- // 3.加入RTC房间
|
|
|
- [strongSelf joinLiveRoom];
|
|
|
- }];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)sendDownSeatMessage {
|
|
|
- KSLiveChatroomDownSeat *downSeatMessage = [[KSLiveChatroomDownSeat alloc] init];
|
|
|
- downSeatMessage.audienceId = UserDefault(IM_USERID);
|
|
|
- downSeatMessage.audienceName = UserDefault(NicknameKey);
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:downSeatMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
- weakSelf.micStatus = MICSTATUS_NOMAL;
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (LiveroomTimeManager *)timeManager {
|
|
|
- if (!_timeManager) {
|
|
|
- _timeManager = [[LiveroomTimeManager alloc] initWithDelegate:self];
|
|
|
- }
|
|
|
- return _timeManager;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSInteger)getCloseTime {
|
|
|
- NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
|
|
|
- [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
|
|
|
- formatter.timeZone = [NSTimeZone systemTimeZone];
|
|
|
- NSDate *currentDate = [NSDate date];
|
|
|
- NSDate *expireDate = [formatter dateFromString:self.liveEndTime];
|
|
|
- NSTimeInterval timeInterval = [expireDate timeIntervalSinceDate:currentDate];
|
|
|
- return self.expiredMinute * 60 + timeInterval;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSShopCardView *)cardView {
|
|
|
- if (!_cardView) {
|
|
|
- _cardView = [KSShopCardView shareInstance];
|
|
|
- MJWeakSelf;
|
|
|
- [_cardView clickAction:^(CART_TYPE type) {
|
|
|
- [weakSelf displayTeacherInfo:type];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _cardView;
|
|
|
-}
|
|
|
-// tabs= practice | 陪练课 live | 直播课 video | 视频课 music | 乐谱 跳转到对应tab页
|
|
|
-
|
|
|
-- (void)displayTeacherInfo:(CART_TYPE)type {
|
|
|
- [self sendRushMessage];
|
|
|
- RCRTCVideoView *videoView = nil;
|
|
|
- for (UIView *view in self.videoView.subviews) {
|
|
|
- if ([view isKindOfClass:[RCRTCVideoView class]]) {
|
|
|
- videoView = (RCRTCVideoView *)view;
|
|
|
- }
|
|
|
- }
|
|
|
- if (videoView) {
|
|
|
- _hasShowSuspendView = YES;
|
|
|
- KSDragWindowManager *manager = [KSDragWindowManager sharedManager];
|
|
|
- [manager initDragWindowWithPhoneLive:YES];
|
|
|
- manager.rootVC = (CustomNavViewController *)self.navigationController;
|
|
|
-
|
|
|
- [videoView removeFromSuperview];
|
|
|
- [manager.dragWindow.containerView addSubview:videoView];
|
|
|
- [videoView mas_updateConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.top.bottom.mas_equalTo(manager.dragWindow.containerView);
|
|
|
- }];
|
|
|
- [manager.dragWindow bringSubviewToFront:manager.dragWindow.cancelButton];
|
|
|
- }
|
|
|
-
|
|
|
- NSString *tabs = @"";
|
|
|
- switch (type) {
|
|
|
- case CART_TYPE_NONE:
|
|
|
- {
|
|
|
- tabs = @"";
|
|
|
- }
|
|
|
- break;
|
|
|
- case CART_TYPE_ACCOMPANY:
|
|
|
- {
|
|
|
- tabs = @"practice";
|
|
|
- }
|
|
|
- break;
|
|
|
- case CART_TYPE_LIVE:
|
|
|
- {
|
|
|
- tabs = @"live";
|
|
|
- }
|
|
|
- break;
|
|
|
- case CART_TYPE_VIDEO:
|
|
|
- {
|
|
|
- tabs = @"video";
|
|
|
- }
|
|
|
- break;
|
|
|
- case CART_TYPE_MUSIC:
|
|
|
- {
|
|
|
- tabs = @"music";
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- NSString *url = @"";
|
|
|
- if ([NSString isEmptyString:tabs]) {
|
|
|
- url = [NSString stringWithFormat:@"%@%@%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId];
|
|
|
- }
|
|
|
- else {
|
|
|
- url = [NSString stringWithFormat:@"%@%@%@&tabs=%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId,tabs];
|
|
|
- }
|
|
|
- KSLiveWebViewController *ctrl = [[KSLiveWebViewController alloc] init];
|
|
|
- ctrl.url = url;
|
|
|
- [self.navigationController pushViewController:ctrl animated:YES];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)sendRushMessage {
|
|
|
-// KSRCShopRushMessage *rushMessage = [[KSRCShopRushMessage alloc] init];
|
|
|
-// rushMessage.userId = UserDefault(UIDKey);
|
|
|
-// rushMessage.userName = UserDefault(NicknameKey);
|
|
|
-// [self sendMessage:rushMessage displayMessage:NO callback:^(BOOL success) {
|
|
|
-//
|
|
|
-// }];
|
|
|
-}
|
|
|
-- (void)showAnimationView:(BOOL)isJoinRoom showMessag:(NSString *)message {
|
|
|
-
|
|
|
- if (self.enterAnimationView && self.enterAnimationView.isShow) {
|
|
|
- return;
|
|
|
- }
|
|
|
- else {
|
|
|
- ANIMATIONTYPE type = isJoinRoom ? ANIMATIONTYPE_JOIN : ANIMATIONTYPE_RUSH;
|
|
|
- self.enterAnimationView = [[LiveAnimationView alloc] initWithTitle:message animationType:type];
|
|
|
- [self.view addSubview:self.enterAnimationView];
|
|
|
- [self.enterAnimationView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.view);
|
|
|
- make.width.mas_equalTo(KPortraitWidth);
|
|
|
- make.height.mas_equalTo(24.0f);
|
|
|
- make.bottom.mas_equalTo(self.messageContentView.mas_top).offset(-6);
|
|
|
- }];
|
|
|
- [self.view bringSubviewToFront:self.enterAnimationView];
|
|
|
-
|
|
|
- MJWeakSelf;
|
|
|
- [self.enterAnimationView startAnimationEndCallback:^{
|
|
|
-
|
|
|
- weakSelf.enterAnimationView.isShow = NO;
|
|
|
- weakSelf.enterAnimationView = nil;
|
|
|
- }];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)dealloc {
|
|
|
- [[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveApplyView *)applyView {
|
|
|
- if (!_applyView) {
|
|
|
- _applyView = [LiveApplyView shareInstance];
|
|
|
- MJWeakSelf;
|
|
|
- [_applyView applySeatCallback:^{
|
|
|
- [weakSelf applySeatAction];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _applyView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)applySeatAction {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"已发起连麦申请"];
|
|
|
- [self sendSeatMessageApply:YES];
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveApplyingView *)applyingView {
|
|
|
- if (!_applyingView) {
|
|
|
- _applyingView = [LiveApplyingView shareInstance];
|
|
|
- NSString *avatar = UserDefaultObjectForKey(AvatarUrlKey);
|
|
|
- [_applyingView.myAvatal sd_setImageWithURL:[NSURL URLWithString:[avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
|
|
|
- [_applyingView.teacherAvatal sd_setImageWithURL:[NSURL URLWithString:[self.createrAvatal getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
|
|
|
- MJWeakSelf;
|
|
|
- [_applyingView cancleApplyCallback:^{
|
|
|
- [weakSelf cancleApplyAction];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _applyingView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)cancleApplyAction {
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [LiveRoomAlertView liveroomAlertWithTitle:@"连麦申请中,确认取消连麦申请吗?" leftButtonTitle:@"取消" rightTitle:@"确定" inView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [weakSelf.applyingView hideView];
|
|
|
- [weakSelf sendSeatMessageApply:NO];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (void)showShareUI:(UIImage *)image {
|
|
|
- [KSUMShareManager shareInstanceWithImage:image url:@"" shareTitle:@"" descMessage:@"" shareType:KSSHARETYPE_IMAGE showInView:self callback:^(BOOL isSuccess, NSString * _Nonnull descMessage) {
|
|
|
- if (isSuccess) {
|
|
|
- [self.shareView hideView];
|
|
|
- }
|
|
|
- else {
|
|
|
-
|
|
|
- }
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:descMessage];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)savePicWithImage:(UIImage *)image {
|
|
|
-
|
|
|
- // 判断相册权限
|
|
|
- PREMISSIONTYPE albumEnable = [RecordCheckManager checkPhotoLibraryPremissionAvaiable:NO showInView:nil];
|
|
|
- if (albumEnable == PREMISSIONTYPE_YES) { // 如果有权限
|
|
|
-
|
|
|
- [[TZImageManager manager] savePhotoWithImage:image completion:^(PHAsset *asset, NSError *error) {
|
|
|
- if (!error) {
|
|
|
- [self .shareView hideView];
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"保存成功"];
|
|
|
- }
|
|
|
- else {
|
|
|
- [LOADING_MANAGER MBShowAUTOHidingInWindow:@"保存图片失败"];
|
|
|
- }
|
|
|
- }];
|
|
|
- }
|
|
|
- else {
|
|
|
- if (albumEnable == PREMISSIONTYPE_NO) {
|
|
|
- [self showAlertWithMessage:@"请开启相册访问权限" type:CHECKDEVICETYPE_CAMREA];
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
|
|
|
- [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [self openSettingView];
|
|
|
- }];
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)openSettingView {
|
|
|
- if (@available(iOS 10, *)) {
|
|
|
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:nil];
|
|
|
- } else {
|
|
|
- [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@end
|