|
@@ -21,6 +21,11 @@
|
|
|
#import "KSLiveEmptyView.h"
|
|
|
#import "KSChatVideoView.h"
|
|
|
#import "LiveRoomLikeLayer.h"
|
|
|
+#import "KSDragWindowManager.h"
|
|
|
+//#import <Lottie/Lottie.h>
|
|
|
+#import "KSShopCardView.h"
|
|
|
+#import "KSLiveWebViewController.h"
|
|
|
+
|
|
|
|
|
|
typedef NS_ENUM(NSInteger, MICSTATUS) {
|
|
|
MICSTATUS_NOMAL, // 正常状态
|
|
@@ -42,6 +47,9 @@ typedef NS_ENUM(NSInteger, MICSTATUS) {
|
|
|
|
|
|
@property (nonatomic) NSMutableArray <KSLiveStreamVideo *>*streamVideos;
|
|
|
|
|
|
+// 视频主窗口容器
|
|
|
+@property (nonatomic, strong) UIView *videoContainerView;
|
|
|
+
|
|
|
@property (nonatomic, strong) KSChatVideoView *videoView;
|
|
|
|
|
|
@property (nonatomic, strong) LiveRoomHeadView *headView;
|
|
@@ -101,6 +109,26 @@ typedef NS_ENUM(NSInteger, MICSTATUS) {
|
|
|
/// 是否在切换身份
|
|
|
@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, assign) BOOL isLostPackage; // 严重丢包
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isBitError; // bit error
|
|
|
+
|
|
|
+//@property (nonatomic, strong) LOTAnimationView *animationView;
|
|
|
+
|
|
|
+@property (nonatomic, assign) BOOL isCloseRoom; // 是否直播结束
|
|
|
+
|
|
|
+@property (nonatomic, strong) KSShopCardView *cardView;
|
|
|
+
|
|
|
@end
|
|
|
|
|
|
// 用于记录点赞消息连续点击的次数
|
|
@@ -120,6 +148,7 @@ static int clickPraiseBtnTimes = 0;
|
|
|
self.micStatus = MICSTATUS_NOMAL;
|
|
|
self.isCreaterInRoom = NO; // 默认主讲人不在房间
|
|
|
self.isImConnected = [USER_MANAGER checkIMConnected];
|
|
|
+ self.isCloseRoom = NO;
|
|
|
}
|
|
|
|
|
|
- (void)viewDidLoad {
|
|
@@ -140,13 +169,52 @@ static int clickPraiseBtnTimes = 0;
|
|
|
}];
|
|
|
}
|
|
|
|
|
|
- [[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)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 integerValueForKey:@"code"] == 200 && [dic boolValueForKey:@"status"]) {
|
|
|
+ // 回调信息
|
|
|
+ MJWeakSelf;
|
|
|
+ [self notiferJoinSuccessToServiceCallback:^{
|
|
|
+ [self MBPShow:@"IM连接成功"];
|
|
|
+ [weakSelf sendWelcomeMessage];
|
|
|
+ }];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ [self MBPShow: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];
|
|
|
+ [self sendMessage:joinChatroomMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
+
|
|
|
+ }];
|
|
|
+ } error:^(RCErrorCode status) {
|
|
|
+ NSLog(@"error code %zd" ,status);
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
- (void)judgeAutoClose {
|
|
|
if (self.isTempRoom == NO) {
|
|
|
self.timeManager.autoCloseNetworkRoomTime = [self getCloseTime];
|
|
@@ -169,13 +237,27 @@ static int clickPraiseBtnTimes = 0;
|
|
|
- (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.videoView];
|
|
|
+ // 视图主容器
|
|
|
+ [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.videoView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
|
make.left.top.bottom.right.mas_equalTo(self.view);
|
|
|
}];
|
|
@@ -249,8 +331,9 @@ static int clickPraiseBtnTimes = 0;
|
|
|
});
|
|
|
KSLiveChatroomWelcome *joinChatroomMessage = [[KSLiveChatroomWelcome alloc] init];
|
|
|
[joinChatroomMessage setMsgId:[RCIM sharedRCIM].currentUserInfo.userId];
|
|
|
+ MJWeakSelf;
|
|
|
[self sendMessage:joinChatroomMessage displayMessage:YES callback:^(BOOL success) {
|
|
|
-
|
|
|
+ weakSelf.hasSendWelcomeMessage = YES;
|
|
|
}];
|
|
|
// 加入成功发送消息
|
|
|
} error:^(RCErrorCode status) {
|
|
@@ -268,6 +351,32 @@ static int clickPraiseBtnTimes = 0;
|
|
|
[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) {
|
|
|
+ for (KSLiveStreamVideo *streamVideo in self.streamVideos) {
|
|
|
+ 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 {
|
|
@@ -281,6 +390,8 @@ static int clickPraiseBtnTimes = 0;
|
|
|
// Fallback on earlier versions
|
|
|
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault;
|
|
|
}
|
|
|
+
|
|
|
+ // 退出房间才停止定时器
|
|
|
if (_timeManager) {
|
|
|
[_timeManager stopDurationTimer];
|
|
|
}
|
|
@@ -288,30 +399,44 @@ static int clickPraiseBtnTimes = 0;
|
|
|
|
|
|
// 刷新seatView
|
|
|
- (void)renderSeatView {
|
|
|
+
|
|
|
NSMutableArray *seatArray = [NSMutableArray array];
|
|
|
- for (RCRTCRemoteUser *user in self.remoteMemberArray) {
|
|
|
+ NSArray *remoteUserArray = [self.room.remoteUsers mutableCopy];
|
|
|
+ for (RCRTCRemoteUser *user in remoteUserArray) {
|
|
|
if (![user.userId isEqualToString:self.videoView.streamUserId] && ![user.userId isEqualToString:self.createrId]) {
|
|
|
[seatArray addObject:user.userId];
|
|
|
}
|
|
|
}
|
|
|
- if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
|
+ if (self.micStatus == MICSTATUS_CONNECTING && ![seatArray containsObject:UserDefault(UIDKey)]) {
|
|
|
[seatArray addObject:UserDefault(UIDKey)];
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
- }];
|
|
|
+ if (![self.videoContainerView.subviews containsObject:self.seatContainer]) {
|
|
|
+ [self.videoContainerView addSubview:self.seatContainer];
|
|
|
+ }
|
|
|
+ [self updateSeatContainerConstraint];
|
|
|
+
|
|
|
self.seatContainer.seatMemberArray = [NSMutableArray arrayWithArray:seatArray];
|
|
|
[self.seatContainer refreshSeatUI];
|
|
|
}
|
|
|
else {
|
|
|
- if ([self.view.subviews containsObject:self.seatContainer]) {
|
|
|
- [self.seatContainer removeFromSuperview];
|
|
|
- }
|
|
|
+ [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];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -845,6 +970,16 @@ static int clickPraiseBtnTimes = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#pragma mark -- 加入直播间和退出直播间回到服务
|
|
|
+- (void)notiferJoinSuccessToServiceCallback:(void(^)(void))callback {
|
|
|
+ callback();
|
|
|
+// [KSNetworkingManager LiveroomJoinRequest:KS_GET roomId:self.roomId userId:UserDefault(UIDKey) success:^(NSDictionary * _Nonnull dic) {
|
|
|
+// callback();
|
|
|
+// } faliure:^(NSError * _Nonnull error) {
|
|
|
+// callback();
|
|
|
+// }];
|
|
|
+}
|
|
|
+
|
|
|
#pragma mark -- 退出直播间回掉服务
|
|
|
- (void)quitNotiferService {
|
|
|
[KSNetworkingManager LiveroomQuit:KS_POST success:^(NSDictionary * _Nonnull dic) {
|
|
@@ -1276,6 +1411,14 @@ static int clickPraiseBtnTimes = 0;
|
|
|
return _videoView;
|
|
|
}
|
|
|
|
|
|
+- (UIView *)videoContainerView {
|
|
|
+ if (!_videoContainerView) {
|
|
|
+ _videoContainerView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
|
+ _videoContainerView.backgroundColor = [UIColor clearColor];
|
|
|
+ }
|
|
|
+ return _videoContainerView;
|
|
|
+}
|
|
|
+
|
|
|
- (LiveRoomHeadView *)headView {
|
|
|
if (!_headView) {
|
|
|
_headView = [LiveRoomHeadView shareInstance];
|
|
@@ -1341,9 +1484,9 @@ static int clickPraiseBtnTimes = 0;
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
- case LIVEROOMACTION_SHOP: // 商店
|
|
|
+ case LIVEROOMACTION_SHOP:
|
|
|
{
|
|
|
-
|
|
|
+ [self showCartAlert];
|
|
|
}
|
|
|
break;
|
|
|
case LIVEROOMACTION_LIKE:
|
|
@@ -1361,6 +1504,9 @@ static int clickPraiseBtnTimes = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+- (void)showCartAlert {
|
|
|
+ [self.cardView showViewInView:self.view];
|
|
|
+}
|
|
|
|
|
|
- (void)quitAction {
|
|
|
if (self.micStatus == MICSTATUS_CONNECTING) {
|
|
@@ -1490,6 +1636,71 @@ static int clickPraiseBtnTimes = 0;
|
|
|
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 {
|
|
|
+
|
|
|
+ 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 initDragWindow];
|
|
|
+ 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_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 = [NSString stringWithFormat:@"%@%@%@&tabs=%@", WEBHOST,@"/#/teacherHome?teacherId=",self.createrId,tabs];
|
|
|
+ KSLiveWebViewController *ctrl = [[KSLiveWebViewController alloc] init];
|
|
|
+ ctrl.url = url;
|
|
|
+ [self.navigationController pushViewController:ctrl animated:YES];
|
|
|
+}
|
|
|
+
|
|
|
- (void)dealloc {
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
}
|