|
@@ -1,1138 +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 "KSNormalAlertView.h"
|
|
|
-#import "KSLiveStreamVideo.h"
|
|
|
-#import "SeatContentView.h"
|
|
|
-#import "LiveSeatApplyView.h"
|
|
|
-#import "LiveroomTimeManager.h"
|
|
|
-#import "SeatTipsView.h"
|
|
|
-//#import "KSPublicAlertView.h"
|
|
|
-
|
|
|
-@interface LiveVideoRoomViewController ()<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) RCRTCLiveInfo *liveInfo;
|
|
|
-@property (nonatomic, strong) KSLiveStreamVideo *localVideo;
|
|
|
-
|
|
|
-@property (nonatomic, strong) UIView *videoView;
|
|
|
-
|
|
|
-@property (nonatomic, strong) LiveRoomHeadView *headView;
|
|
|
-
|
|
|
-@property (nonatomic, copy) LiveRoomBottomView *bottomView;
|
|
|
-
|
|
|
-/// 提示窗
|
|
|
-@property (nonatomic, strong) KSNormalAlertView *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, strong) LiveSeatApplyView *seatApplyView;
|
|
|
-
|
|
|
-@property (nonatomic, strong) NSMutableArray *seatApplyArray; // 申请连麦数组
|
|
|
-
|
|
|
-// 远端连麦用户
|
|
|
-@property (nonatomic, strong) NSMutableArray *remoteMemberArray;
|
|
|
-
|
|
|
-/// 连麦申请统计数据
|
|
|
-@property (nonatomic, strong) SeatTipsView *seatApplyTips;
|
|
|
-
|
|
|
-@property (nonatomic, assign) BOOL isQuitRoom; // 是否正在退出房间
|
|
|
-
|
|
|
-@end
|
|
|
-
|
|
|
-@implementation LiveVideoRoomViewController
|
|
|
-
|
|
|
-- (instancetype)init {
|
|
|
- self = [super init];
|
|
|
- if (self) {
|
|
|
- [self defaultConfig];
|
|
|
- }
|
|
|
- return self;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)defaultConfig {
|
|
|
- self.isImConnected = [USER_MANAGER checkIMConnected];
|
|
|
-}
|
|
|
-
|
|
|
-- (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];
|
|
|
- });
|
|
|
- }];
|
|
|
- }
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomLogOut) name:@"liveroomLogout" object:nil];
|
|
|
-
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(liveroomQuit) name:@"liveroomQuit" object:nil];
|
|
|
-
|
|
|
- [self judgeAutoClose];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)judgeAutoClose {
|
|
|
- if (self.isTempRoom == NO) {
|
|
|
- self.timeManager.autoCloseNetworkRoomTime = [self getCloseTime];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)liveroomLogOut {
|
|
|
- if (self.isQuitRoom) {
|
|
|
- return;
|
|
|
- }
|
|
|
- [self MBPShow:@"该账号在其他设备上登录"];
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitAction];
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-- (void)liveroomQuit {
|
|
|
- if (self.isQuitRoom) {
|
|
|
- return;
|
|
|
- }
|
|
|
- dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
|
- [self quitAction];
|
|
|
- });
|
|
|
-}
|
|
|
-
|
|
|
-- (void)registerNotification {
|
|
|
- [KSChatroomMessageCenter registerMessageTypes];
|
|
|
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMessageNotification:) name:OnReceiveChatroomMessageNotification object:nil];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setupUI {
|
|
|
- CGSize size = self.view.bounds.size;
|
|
|
- self.view.backgroundColor = HexRGB(0x25292e);
|
|
|
-
|
|
|
- [self.view addSubview:self.videoView];
|
|
|
- [self.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.top.bottom.right.mas_equalTo(self.view);
|
|
|
- }];
|
|
|
-
|
|
|
- [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.headView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.view);
|
|
|
- make.height.mas_equalTo(90);
|
|
|
- if (@available(iOS 11.0, *)) {
|
|
|
- make.top.mas_equalTo(self.view.mas_safeAreaLayoutGuideTop).offset(10);
|
|
|
- } else {
|
|
|
- // Fallback on earlier versions
|
|
|
- make.top.mas_equalTo(self.view.mas_top).offset(10);
|
|
|
- }
|
|
|
- }];
|
|
|
- [self.view addSubview:self.messageContentView];
|
|
|
- [self.view addSubview:self.bottomView];
|
|
|
-
|
|
|
- [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(270);
|
|
|
- }];
|
|
|
- [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(240);
|
|
|
- make.bottom.mas_equalTo(self.messageContentView.mas_bottom);
|
|
|
- }];
|
|
|
-
|
|
|
- [self.view addSubview:self.seatApplyTips];
|
|
|
- [self.seatApplyTips hideView];
|
|
|
- [self.seatApplyTips mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.bottom.mas_equalTo(self.bottomView.mas_top).offset(2);
|
|
|
- make.height.mas_equalTo(20);
|
|
|
- make.left.mas_equalTo(self.bottomView.mas_right).offset(-72);
|
|
|
- }];
|
|
|
-
|
|
|
- UITapGestureRecognizer *resetBottomTapGesture =[[UITapGestureRecognizer alloc]
|
|
|
- initWithTarget:self
|
|
|
- action:@selector(resetBottomGesture:)];
|
|
|
- resetBottomTapGesture.delegate = self;
|
|
|
- [self.view addGestureRecognizer:resetBottomTapGesture];
|
|
|
-}
|
|
|
-
|
|
|
-- (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];
|
|
|
- [self sendMessage:joinChatroomMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
-
|
|
|
- }];
|
|
|
- // 加入成功发送消息
|
|
|
- } error:^(RCErrorCode status) {
|
|
|
- if (status == RC_CHATROOM_NOT_EXIST || status == KICKED_FROM_CHATROOM || status == RC_PARAMETER_INVALID_CHATROOM) {
|
|
|
- dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
- [self MBPShow:@"加入聊天室失败"];
|
|
|
- });
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)viewWillAppear:(BOOL)animated {
|
|
|
- [super viewWillAppear:animated];
|
|
|
- [UIApplication sharedApplication].idleTimerDisabled = YES;
|
|
|
- [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
|
|
|
- [IQKeyboardManager sharedManager].enable = NO;
|
|
|
- [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
|
|
|
-}
|
|
|
-
|
|
|
-- (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];
|
|
|
- for (RCRTCRemoteUser *user in self.remoteMemberArray) {
|
|
|
- [seatArray addObject:user.userId];
|
|
|
- }
|
|
|
- if (seatArray.count) {
|
|
|
- [self.view addSubview:self.seatContainer];
|
|
|
- [self.seatContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.mas_equalTo(self.view);
|
|
|
- make.top.mas_equalTo(self.headView.mas_bottom).offset(10);
|
|
|
- make.height.mas_equalTo(80);
|
|
|
- }];
|
|
|
- self.seatContainer.seatMemberArray = [NSMutableArray arrayWithArray:seatArray];
|
|
|
- [self.seatContainer refreshSeatUI];
|
|
|
- }
|
|
|
- else {
|
|
|
- if ([self.view.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;
|
|
|
-
|
|
|
- if (count > 10000) {
|
|
|
- count = count / 10000;
|
|
|
- desc = [NSString stringWithFormat:@"%zd万+人",count];
|
|
|
- }
|
|
|
- else {
|
|
|
- desc = [NSString stringWithFormat:@"%zd人",count];
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)setRoleType {
|
|
|
- // 1.设置切换听筒为扬声器
|
|
|
- [self.engine enableSpeaker:YES];
|
|
|
- // 2.添加本地采集预览界面
|
|
|
- [self setupLocalVideoView];
|
|
|
- // 3.加入RTC房间
|
|
|
- [self joinLiveRoom];
|
|
|
-}
|
|
|
-
|
|
|
-- (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)setupLocalVideoView {
|
|
|
- [self.videoView addSubview:self.localVideo.canvesView];
|
|
|
- [self.localVideo.canvesView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
- make.left.right.top.bottom.mas_equalTo(self.videoView);
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-#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];
|
|
|
- [self MBPShow:errorStr];
|
|
|
- return;
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)didUnpublishStreams:(NSArray<RCRTCInputStream *> *)streams {
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-- (void)didOfflineUser:(RCRTCRemoteUser *)user {
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-// 远端用户切换身份
|
|
|
-- (void)didSwitchRoleWithUser:(RCRTCRemoteUser *)user roleType:(RCRTCLiveRoleType)roleType {
|
|
|
- if (roleType == RCRTCLiveRoleTypeBroadcaster) {
|
|
|
- if ([self judgeContainUser:user.userId] == NO) {
|
|
|
- [self.remoteMemberArray addObject:user];
|
|
|
- // 刷新连麦成员状态数据
|
|
|
- if ([self judgeContainMember:user.userId]) {
|
|
|
- // 更新状态
|
|
|
- [self updateMemberStatus:user.userId];
|
|
|
- [self refreshSeatApplyView];
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else {
|
|
|
- [self removeMemberUserId:user.userId];
|
|
|
- // 刷新连麦成员数据
|
|
|
- if ([self judgeContainMember:user.userId]) {
|
|
|
- [self removeMember:user.userId];
|
|
|
- [self refreshSeatApplyView];
|
|
|
- }
|
|
|
- }
|
|
|
- [self renderSeatView];
|
|
|
-
|
|
|
- NSLog(@"didSwitchRoleWithUser --------");
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)judgeContainUser:(NSString *)userId {
|
|
|
- BOOL containUser = NO;
|
|
|
- for (RCRTCRemoteUser *remoteUser in self.remoteMemberArray) {
|
|
|
- if ([remoteUser.userId isEqualToString:userId]) {
|
|
|
- containUser = YES;
|
|
|
- }
|
|
|
- }
|
|
|
- return containUser;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)removeMemberUserId:(NSString *)userId {
|
|
|
- for (RCRTCRemoteUser *remoteUser in self.remoteMemberArray) {
|
|
|
- if ([remoteUser.userId isEqualToString:userId]) {
|
|
|
- [self.remoteMemberArray removeObject:remoteUser];
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#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 {
|
|
|
- [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 = RCRTCLiveRoleTypeBroadcaster;
|
|
|
- __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]);
|
|
|
-// [strongSelf MBPShow:@"加入直播间失败"];
|
|
|
-// [strongSelf.navigationController dismissViewControllerAnimated:YES completion:nil];
|
|
|
-// }
|
|
|
-// else { // 加入直播间成功
|
|
|
- strongSelf.room = room;
|
|
|
- strongSelf.room.delegate = self;
|
|
|
- [strongSelf countMemberCount];
|
|
|
- // 发布本地视频流
|
|
|
- [self publishLocalStream];
|
|
|
-// }
|
|
|
- });
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)publishLocalStream {
|
|
|
- // 1.设置渲染视图渲染视图
|
|
|
- [self.engine.defaultVideoStream setVideoView:self.localVideo.canvesView];
|
|
|
- // 2.设置视频流参数
|
|
|
- RCRTCVideoStreamConfig *videoConfig = self.engine.defaultVideoStream.videoConfig;
|
|
|
- videoConfig.videoSizePreset = RCRTCVideoSizePreset1280x720;
|
|
|
- [self.engine.defaultVideoStream setVideoConfig:videoConfig];
|
|
|
- // 3.开始视频采集
|
|
|
- [self.engine.defaultVideoStream startCapture];
|
|
|
- // 发布本地视频流到放假
|
|
|
- [self.room.localUser publishDefaultLiveStreams:^(BOOL isSuccess, RCRTCCode code, RCRTCLiveInfo * _Nullable liveInfo) {
|
|
|
- if (code == RCRTCCodeSuccess) {
|
|
|
- self.liveInfo = liveInfo;
|
|
|
- }
|
|
|
- else {
|
|
|
- [self MBPShow:@"视频流发布失败"];
|
|
|
- }
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)exitRoom {
|
|
|
- __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];
|
|
|
- }];
|
|
|
- });
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-#pragma mark -- 退出直播间回掉服务
|
|
|
-- (void)quitNotiferService {
|
|
|
- [KSNetworkingManager LiveroomQuit:KS_POST success:^(NSDictionary * _Nonnull dic) {
|
|
|
- if ([dic integerValueForKey:@"errCode"] == 0) {
|
|
|
- NSLog(@"success");
|
|
|
- }
|
|
|
- else {
|
|
|
- NSLog(@"----- error %@", [dic 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]]) {
|
|
|
- KSLiveChatroomLike *likeMessage = (KSLiveChatroomLike *)rcMessage.content;
|
|
|
- // 统计点赞数量
|
|
|
- __blockSelf.likeCount += likeMessage.counts;
|
|
|
- [__blockSelf countLikeMessageCount];
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomWelcome class]]) {
|
|
|
- // 过滤自己发送的欢迎消息
|
|
|
- if ([rcMessage.senderUserId isEqualToString:UserDefault(UIDKey)]) {
|
|
|
- return;
|
|
|
- }
|
|
|
- __blockSelf.totalCount++;
|
|
|
- [__blockSelf countMemberCount];
|
|
|
- }
|
|
|
- // 用户退出消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomLeave class]]) {
|
|
|
- KSLiveChatroomLeave *memberLeaveMsg = (KSLiveChatroomLeave *)rcMessage.content;
|
|
|
- __blockSelf.totalCount--;
|
|
|
- [__blockSelf countMemberCount];
|
|
|
- if ([__blockSelf judgeContainMember:memberLeaveMsg.userId]) {
|
|
|
- [__blockSelf removeMember:memberLeaveMsg.userId];
|
|
|
- [__blockSelf refreshSeatApplyView];
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- // 用户退出消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomUserQuit class]]) {
|
|
|
- KSLiveChatroomUserQuit *memberLeaveMsg = (KSLiveChatroomUserQuit *)rcMessage.content;
|
|
|
- __blockSelf.totalCount--;
|
|
|
- [__blockSelf countMemberCount];
|
|
|
- if ([__blockSelf judgeContainMember:memberLeaveMsg.userId]) {
|
|
|
- [__blockSelf removeMember:memberLeaveMsg.userId];
|
|
|
- [__blockSelf refreshSeatApplyView];
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- // 连麦申请消息
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomSeatApply class]]) {
|
|
|
- KSLiveChatroomSeatApply *seatApplyMessage = (KSLiveChatroomSeatApply *)rcMessage.content;
|
|
|
-
|
|
|
- if (seatApplyMessage.type == SEATHANDLE_APPLY) { // 观众申请 加入申请中
|
|
|
- LiveSeatMember *member = [[LiveSeatMember alloc] init];
|
|
|
- member.avatar = seatApplyMessage.audienceAvatar;
|
|
|
- member.name = seatApplyMessage.audienceName;
|
|
|
- member.userId = seatApplyMessage.audienceId;
|
|
|
- member.isConnected = NO;
|
|
|
- if (![__blockSelf judgeContainMember:member.userId]) {
|
|
|
- [__blockSelf.seatApplyArray addObject:member];
|
|
|
- [__blockSelf refreshSeatApplyView];
|
|
|
- }
|
|
|
- }
|
|
|
- else if (seatApplyMessage.type == SEATHANDLE_CANCELAPPLY) { // 观众取消申请 从申请中剔除
|
|
|
- if ([__blockSelf judgeContainMember:seatApplyMessage.audienceId]) {
|
|
|
- [__blockSelf removeMember:seatApplyMessage.audienceId];
|
|
|
- [__blockSelf refreshSeatApplyView];
|
|
|
- }
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
- // 连麦回复消息(暂不处理)
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomSeatResponse class]]) {
|
|
|
-
|
|
|
- }
|
|
|
- else if ([rcMessage.content isMemberOfClass:[KSLiveChatroomDownSeat class]]) { // 观众下麦,从列表中移除
|
|
|
- KSLiveChatroomDownSeat *downSeatMessage = (KSLiveChatroomDownSeat *)rcMessage.content;
|
|
|
- if ([__blockSelf judgeContainMember:downSeatMessage.audienceId]) {
|
|
|
- [__blockSelf removeMember:downSeatMessage.audienceId];
|
|
|
- [__blockSelf refreshSeatApplyView];
|
|
|
- }
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // left
|
|
|
- NSDictionary *leftDic = notification.userInfo;
|
|
|
- if (leftDic && [leftDic[@"left"] isEqual:@(0)]) {
|
|
|
- __blockSelf.isNeedScrollToButtom = YES;
|
|
|
- }
|
|
|
- [__blockSelf appendAndDisplayMessage:rcMessage];
|
|
|
- }
|
|
|
-
|
|
|
- });
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (BOOL)judgeContainMember:(NSString *)userId {
|
|
|
- for (LiveSeatMember *obj in self.seatApplyArray) {
|
|
|
- if ([obj.userId isEqualToString:userId]) {
|
|
|
- return YES;
|
|
|
- }
|
|
|
- }
|
|
|
- return NO;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)removeMember:(NSString *)memberId {
|
|
|
- for (LiveSeatMember *member in self.seatApplyArray) {
|
|
|
- if ([member.userId isEqualToString:memberId]) {
|
|
|
- [self.seatApplyArray removeObject:member];
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)updateMemberStatus:(NSString *)userId {
|
|
|
- for (LiveSeatMember *obj in self.seatApplyArray) {
|
|
|
- if ([obj.userId isEqualToString:userId]) {
|
|
|
- obj.isConnected = YES;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)refreshSeatApplyView {
|
|
|
- if (self.seatApplyArray.count) {
|
|
|
- [self showSeatTips:self.seatApplyArray.count];
|
|
|
- }
|
|
|
- else {
|
|
|
- [self hideSeatTips];
|
|
|
- }
|
|
|
- [self.seatApplyView refreshSeatApplyTable:self.seatApplyArray];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)showSeatTips:(NSInteger)count {
|
|
|
- NSString *countDesc = count >= 100 ? @"99+" : [NSString stringWithFormat:@"%zd",count];
|
|
|
- [self.seatApplyTips configCountMessage:countDesc];
|
|
|
- [self.seatApplyTips showTipsView];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)hideSeatTips {
|
|
|
- [self.seatApplyTips 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 {
|
|
|
- [self MBPShow:@"直播课已结束!"];
|
|
|
- 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(UIDKey);
|
|
|
- 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(), ^{
|
|
|
- [self MBPShow:@"聊天已被解散,请退出后重进。"];
|
|
|
- });
|
|
|
- }
|
|
|
- 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>100) {
|
|
|
- // 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]]){
|
|
|
- [cell setDataModel:model createrId:self.createrId];
|
|
|
- }
|
|
|
- return cell;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-#pragma mark --- lazying
|
|
|
-- (UIView *)videoView {
|
|
|
- if (!_videoView) {
|
|
|
- _videoView = [[UIView alloc] initWithFrame:self.view.bounds];
|
|
|
- _videoView.backgroundColor = [UIColor clearColor];
|
|
|
- }
|
|
|
- return _videoView;
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveRoomHeadView *)headView {
|
|
|
- if (!_headView) {
|
|
|
- _headView = [LiveRoomHeadView shareInstance];
|
|
|
- }
|
|
|
- return _headView;
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveRoomBottomView *)bottomView {
|
|
|
- if (!_bottomView) {
|
|
|
- _bottomView = [LiveRoomBottomView shareInstance];
|
|
|
- MJWeakSelf;
|
|
|
- [_bottomView bottomClickAction:^(LIVEROOMACTION action) {
|
|
|
- [weakSelf bottomViewAction:action];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _bottomView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)bottomViewAction:(LIVEROOMACTION)action {
|
|
|
- switch (action) {
|
|
|
- case LIVEROOMACTION_CHAT: // 聊天
|
|
|
- {
|
|
|
- [_inputBar setHidden:NO];
|
|
|
- [_inputBar setInputBarStatus:KSBottomBarStatusKeyboard];
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVEROOMACTION_SEAT: // 呼出连麦页面
|
|
|
- {
|
|
|
- [self displaySeatView];
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVEROOMACTION_QUIT: // 退出
|
|
|
- {
|
|
|
- [self quitAction];
|
|
|
- }
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (SeatTipsView *)seatApplyTips {
|
|
|
- if (!_seatApplyTips) {
|
|
|
- _seatApplyTips = [[SeatTipsView alloc] init];
|
|
|
- }
|
|
|
- return _seatApplyTips;
|
|
|
-}
|
|
|
-- (void)displaySeatView {
|
|
|
- [self.view addSubview:self.seatApplyView];
|
|
|
- [self refreshSeatApplyView];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)quitAction {
|
|
|
- self.isQuitRoom = YES;
|
|
|
- MJWeakSelf;
|
|
|
- self.alertView = [KSNormalAlertView ks_showAlertWithTitle:@"确认退出直播间吗?" leftTitle:@"取消" rightTitle:@"确定" inView:self.view cancel:^{
|
|
|
-
|
|
|
- } confirm:^{
|
|
|
- [weakSelf quitRoom];
|
|
|
- }];
|
|
|
-}
|
|
|
-
|
|
|
-- (void)quitRoom {
|
|
|
- // 退出房间
|
|
|
- [self exitRoom];
|
|
|
- [self.navigationController dismissViewControllerAnimated:YES completion:nil];
|
|
|
-}
|
|
|
-
|
|
|
-- (RCRTCEngine *)engine {
|
|
|
- if (!_engine) {
|
|
|
- _engine = [RCRTCEngine sharedInstance];
|
|
|
- [_engine setStatusReportDelegate:self];
|
|
|
- }
|
|
|
- return _engine;
|
|
|
-}
|
|
|
-
|
|
|
-- (KSLiveStreamVideo *)localVideo {
|
|
|
- if (!_localVideo) {
|
|
|
- _localVideo = [KSLiveStreamVideo LocalStreamVideo];
|
|
|
- }
|
|
|
- return _localVideo;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSMutableArray *)remoteMemberArray {
|
|
|
- if (!_remoteMemberArray) {
|
|
|
- _remoteMemberArray = [NSMutableArray array];
|
|
|
- }
|
|
|
- return _remoteMemberArray;
|
|
|
-}
|
|
|
-
|
|
|
-- (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;
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveSeatApplyView *)seatApplyView {
|
|
|
- if (!_seatApplyView) {
|
|
|
- _seatApplyView = [LiveSeatApplyView shareInstance];
|
|
|
- _seatApplyView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
|
|
|
- MJWeakSelf;
|
|
|
- [_seatApplyView operationMemberAction:^(LIVESEATACTION action, LiveSeatMember * _Nonnull member) {
|
|
|
- [weakSelf opreationSeatStudentAction:action member:member];
|
|
|
- }];
|
|
|
- }
|
|
|
- return _seatApplyView;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)opreationSeatStudentAction:(LIVESEATACTION)action member:(LiveSeatMember *)member {
|
|
|
- switch (action) {
|
|
|
- case LIVESEATACTION_APPROVE: // 同意
|
|
|
- {
|
|
|
- KSLiveChatroomSeatResponse *responseMessage = [[KSLiveChatroomSeatResponse alloc] init];
|
|
|
- responseMessage.type = SEATRESPONSE_TEACHERAPPROVE;
|
|
|
- responseMessage.teacherId = self.createrId;
|
|
|
- responseMessage.teacherName = self.createrName;
|
|
|
- responseMessage.audienceId = member.userId;
|
|
|
- responseMessage.audienceName = member.name;
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:responseMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- [weakSelf refreshSeatArrayRemoveMember:NO member:member];
|
|
|
- }];
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVESEATACTION_REJECT: // 拒绝
|
|
|
- {
|
|
|
- KSLiveChatroomSeatResponse *responseMessage = [[KSLiveChatroomSeatResponse alloc] init];
|
|
|
- responseMessage.type = SEATRESPONSE_TEACHERREJECT;
|
|
|
- responseMessage.teacherId = self.createrId;
|
|
|
- responseMessage.teacherName = self.createrName;
|
|
|
- responseMessage.audienceId = member.userId;
|
|
|
- responseMessage.audienceName = member.name;
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:responseMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- [weakSelf refreshSeatArrayRemoveMember:YES member:member];
|
|
|
- }];
|
|
|
- }
|
|
|
- break;
|
|
|
- case LIVESEATACTION_KICK: // 下麦
|
|
|
- {
|
|
|
-
|
|
|
- KSLiveChatroomSeatApply *kickSeatMessage = [[KSLiveChatroomSeatApply alloc] init];
|
|
|
- kickSeatMessage.type = SEATHANDLE_KICKSEAT;
|
|
|
- kickSeatMessage.teacherId = self.createrId;
|
|
|
- kickSeatMessage.teacherName = self.createrName;
|
|
|
- kickSeatMessage.audienceId = member.userId;
|
|
|
- kickSeatMessage.audienceName = member.name;
|
|
|
- MJWeakSelf;
|
|
|
- [self sendMessage:kickSeatMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
- [weakSelf refreshSeatArrayRemoveMember:YES member:member];
|
|
|
- }];
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-- (void)refreshSeatArrayRemoveMember:(BOOL)isRemove member:(LiveSeatMember *)member {
|
|
|
- if (isRemove) {
|
|
|
- [self.seatApplyArray removeObject:member];
|
|
|
- }
|
|
|
- else {
|
|
|
- member.isConnected = YES;
|
|
|
- }
|
|
|
- [self refreshSeatApplyView];
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-- (NSMutableArray *)seatApplyArray {
|
|
|
- if (!_seatApplyArray) {
|
|
|
- _seatApplyArray = [NSMutableArray array];
|
|
|
- }
|
|
|
- return _seatApplyArray;
|
|
|
-}
|
|
|
-
|
|
|
-- (LiveroomTimeManager *)timeManager {
|
|
|
- if (!_timeManager) {
|
|
|
- _timeManager = [[LiveroomTimeManager alloc] initWithDelegate:self];
|
|
|
- _timeManager.autoCloseNetworkRoomTime = self.expiredMinute;
|
|
|
- _timeManager.endClassTime = self.liveEndTime;
|
|
|
- }
|
|
|
- return _timeManager;
|
|
|
-}
|
|
|
-
|
|
|
-- (NSInteger)getCloseTime {
|
|
|
- NSDateFormatter *formatter = [NSObject getDateformatter];
|
|
|
- [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
|
|
|
- NSDate *currentDate = [NSDate date];
|
|
|
- NSDate *expireDate = [formatter dateFromString:self.liveEndTime];
|
|
|
- NSTimeInterval timeInterval = [expireDate timeIntervalSinceDate:currentDate];
|
|
|
- return self.expiredMinute * 60 + timeInterval;
|
|
|
-}
|
|
|
-
|
|
|
-- (void)dealloc {
|
|
|
- [[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
-}
|
|
|
-
|
|
|
-@end
|