cdts/xdts-ios 3/TUICalling/Source/TUICalling.m
2023-07-27 09:20:00 +08:00

743 lines
27 KiB
Objective-C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// TUICalling.m
// TUICalling
//
// Created by noah on 2021/8/28.
//
#import "TUICalling.h"
#import "TRTCCallingUtils.h"
#import "TRTCCallingDelegate.h"
#import "TRTCCalling.h"
#import <ImSDK_Plus/ImSDK_Plus.h>
#import "CallingLocalized.h"
#import "TRTCCalling+Signal.h"
#import "TUICallingBaseView.h"
#import "TUICallingView.h"
#import "TUIGroupCallingView.h"
#import "TRTCGCDTimer.h"
#import "TUICallingAudioPlayer.h"
#import "TUICallingConstants.h"
#import "TRTCCallingHeader.h"
#import <TUICore/TUIDefine.h>
#import <TUICore/TUILogin.h>
typedef NS_ENUM(NSUInteger, TUICallingUserRemoveReason) {
TUICallingUserRemoveReasonLeave,
TUICallingUserRemoveReasonReject,
TUICallingUserRemoveReasonNoresp,
TUICallingUserRemoveReasonBusy
};
@interface TUICalling () <TRTCCallingDelegate, TUIInvitedActionProtocal, TUILoginListener>
/// 存储监听者对象
@property (nonatomic, weak) id<TUICallingListerner> listener;
///Calling 主视图
@property (nonatomic, strong) TUICallingBaseView *callingView;
/// 记录当前的呼叫类型 语音、视频
@property (nonatomic, assign) TUICallingType currentCallingType;
/// 记录当前的呼叫用户类型 主动、被动
@property (nonatomic, assign) TUICallingRole currentCallingRole;
/// 记录是否开启静音模式 需考虑恢复默认页面
@property (nonatomic, assign) BOOL enableMuteMode;
/// 记录是否开启悬浮窗
@property (nonatomic, assign) BOOL enableFloatWindow;
/// 记录是否自定义视图
@property (nonatomic, assign) BOOL enableCustomViewRoute;
/// 记录IM专属 groupID
@property (nonatomic, copy) NSString *groupID;
/// 记录原始userIDs数据不包括自己
@property (nonatomic, strong) NSArray<NSString *> *userIDs;
/// 记录计时器名称
@property (nonatomic, copy) NSString *timerName;
/// 记录通话时间 单位:秒
@property (nonatomic, assign) NSInteger totalTime;
/// 记录是否需要继续播放来电铃声
@property (nonatomic, assign) BOOL needContinuePlaying;
@end
@implementation TUICalling
+ (instancetype)shareInstance {
static dispatch_once_t onceToken;
static TUICalling * t_sharedInstance = nil;
dispatch_once(&onceToken, ^{
t_sharedInstance = [[TUICalling alloc] init];
});
return t_sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_enableMuteMode = NO;
_enableFloatWindow = NO;
_currentCallingRole = NO;
_enableCustomViewRoute = NO;
[[TRTCCalling shareInstance] addDelegate:self];
[TUILogin addLoginListener:self];
[self registerNotifications];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Public method
- (void)call:(NSArray<NSString *> *)userIDs type:(TUICallingType)type {
if (![TUICommonUtil checkArrayValid:userIDs]) {
return;
}
if ([[TUICallingFloatingWindowManager shareInstance] isFloating]) {
[self makeToast:TUICallingLocalize(@"Demo.TRTC.Calling.UnableToRestartTheCall")];
return;
}
// 最大支持9人超过9人不能发起通话
if (userIDs.count > MAX_USERS) {
[self makeToast:TUICallingLocalize(@"Demo.TRTC.Calling.User.Exceed.Limit")];
return;
}
self.userIDs = [NSArray arrayWithArray:userIDs];
self.currentCallingType = type;
self.currentCallingRole = TUICallingRoleCall;
if ([self checkAuthorizationStatusIsDenied] || !self.currentUserId) {
return;
}
[[TRTCCalling shareInstance] groupCall:userIDs type:[self transformCallingType:type] groupID:self.groupID ?: nil];
__weak typeof(self)weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[self.currentUserId] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
__strong typeof(weakSelf)self = weakSelf;
CallUserModel *userModel = [self covertUser:infoList.firstObject];
if (userIDs.count >= 2 || self.groupID.length > 0) {
[self initCallingViewIsGroup:YES];
[self.callingView setCurrentUser:userModel];
NSMutableArray *ids = [NSMutableArray arrayWithArray:userIDs];
[ids addObject:self.currentUserId];
[self configCallViewWithUserIDs:[ids copy] sponsor:nil];
} else {
[self initCallingViewIsGroup:NO];
[self configCallViewWithUserIDs:userIDs sponsor:nil];
}
[self callStartWithUserIDs:userIDs type:type role:TUICallingRoleCall];
} fail:^(int code, NSString *desc) {
NSLog(@"Calling Error: code %d, msg %@", code, desc);
}];
}
- (void)setCallingListener:(id<TUICallingListerner>)listener {
if (listener) {
self.listener = listener;
}
}
- (void)setCallingBell:(NSString *)filePath {
if(!(filePath && [filePath isKindOfClass:NSString.class] && filePath.length > 0)) {
return;
}
if ([filePath hasPrefix:@"http"]) {
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:filePath] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error != nil) {
TRTCLog(@"SetCallingBell Error: %@", error.localizedDescription);
return;
}
if (location != nil) {
NSString *oldBellFilePath = [NSUserDefaults.standardUserDefaults objectForKey:CALLING_BELL_KEY];
[[NSFileManager defaultManager] removeItemAtPath:oldBellFilePath error:nil];
NSString *filePathStr = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePathStr] error:nil];
[NSUserDefaults.standardUserDefaults setObject:filePathStr ?: @"" forKey:CALLING_BELL_KEY];
[NSUserDefaults.standardUserDefaults synchronize];
}
}];
[downloadTask resume];
} else {
[NSUserDefaults.standardUserDefaults setObject:filePath forKey:CALLING_BELL_KEY];
[NSUserDefaults.standardUserDefaults synchronize];
}
}
- (void)setUserNickname:(NSString *)nickname callback:(TUICallingCallback)callback {
[self setUserNickname:nickname avatar:nil callback:callback];
}
- (void)setUserAvatar:(NSString *)avatar callback:(TUICallingCallback)callback {
[self setUserNickname:nil avatar:avatar callback:callback];
}
- (void)enableMuteMode:(BOOL)enable {
self.enableMuteMode = enable;
[[TRTCCalling shareInstance] setMicMute:enable];
}
- (void)enableFloatWindow:(BOOL)enable {
self.enableFloatWindow = enable;
}
- (void)enableCustomViewRoute:(BOOL)enable {
self.enableCustomViewRoute = enable;
}
#pragma mark - Private method
- (void)registerNotifications {
if (@available(iOS 13.0, *)) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appWillEnterForeground)
name:UISceneWillEnterForegroundNotification object:nil];
} else {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appWillEnterForeground)
name:UIApplicationWillEnterForegroundNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(loginSuccessNotification)
name:TUILoginSuccessNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(logoutSuccessNotification)
name:TUILogoutSuccessNotification object:nil];
}
- (void)appWillEnterForeground {
if (self.needContinuePlaying) {
[self playAudioToCalled];
}
self.needContinuePlaying = NO;
}
- (void)loginSuccessNotification {
[[TRTCCalling shareInstance] addDelegate:self];
}
- (void)logoutSuccessNotification {
[[TRTCCalling shareInstance] hangup];
[TRTCCalling destroySharedInstance];
}
- (void)setGroupID:(NSString *)groupID onlineUserOnly:(NSNumber *)onlineUserOnly {
self.groupID = groupID;
[TRTCCalling shareInstance].onlineUserOnly = [onlineUserOnly boolValue];
}
- (void)setGroupID:(NSString *)groupID {
_groupID = groupID;
}
- (void)callStartWithUserIDs:(NSArray *)userIDs type:(TUICallingType)type role:(TUICallingRole)role {
UIViewController *callVC = nil;
if (self.enableCustomViewRoute) {
callVC = [[UIViewController alloc] init];
callVC.view.backgroundColor = [UIColor clearColor];
[callVC.view addSubview:self.callingView];
} else {
[self.callingView showCallingViewEnableFloatWindow:self.enableFloatWindow];
}
if (self.listener && [self.listener respondsToSelector:@selector(callStart:type:role:viewController:)]) {
[self.listener callStart:userIDs type:type role:role viewController:callVC];
}
if (self.enableMuteMode) {
return;
}
if (role == TUICallingRoleCall) {
playAudio(CallingAudioTypeDial);
return;
}
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
self.needContinuePlaying = YES;
return;
}
[self playAudioToCalled];
}
- (void)playAudioToCalled {
NSString *bellFilePath = [NSUserDefaults.standardUserDefaults objectForKey:CALLING_BELL_KEY];
if (bellFilePath && playAudioWithFilePath(bellFilePath)) {
return;
}
playAudio(CallingAudioTypeCalled);
}
- (void)handleStopAudio {
stopAudio();
self.needContinuePlaying = NO;
}
- (void)handleCallEnd {
if (self.listener && [self.listener respondsToSelector:@selector(callEnd:type:role:totalTime:)]) {
[self.listener callEnd:self.userIDs type:self.currentCallingType role:self.currentCallingRole totalTime:(CGFloat)self.totalTime];
}
[self.callingView disMissCalingView];
self.callingView = nil;
[self handleStopAudio];
[TRTCGCDTimer canelTimer:self.timerName];
[self enableAutoLockScreen:YES];
self.timerName = nil;
self.groupID = nil;
}
- (void)handleCallEvent:(TUICallingEvent)event message:(NSString *)message {
if (self.listener && [self.listener respondsToSelector:@selector(onCallEvent:type:role:message:)]) {
[self.listener onCallEvent:event type:self.currentCallingType role:self.currentCallingRole message:message];
}
}
- (void)enableAutoLockScreen:(BOOL)isEnable {
[UIApplication sharedApplication].idleTimerDisabled = !isEnable;
}
- (void)setUserNickname:(NSString *)nickname avatar:(NSString *)avatar callback:(TUICallingCallback)callback {
[[V2TIMManager sharedInstance] getUsersInfo:@[TUILogin.getUserID ?: @""] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *info = infoList.firstObject;
if ((nickname && [nickname isKindOfClass:NSString.class] && [nickname isEqualToString:info.nickName]) ||
(avatar && [avatar isKindOfClass:NSString.class] && [avatar isEqualToString:info.faceURL])) {
callback(0, @"success");
return;
}
if ([nickname isKindOfClass:NSString.class] && nickname.length > 0) {
info.nickName = nickname;
}
if ([avatar isKindOfClass:NSString.class] && avatar.length > 0) {
info.faceURL = avatar;
}
[[V2TIMManager sharedInstance] setSelfInfo:info succ:^{
callback(0, @"success");
} fail:^(int code, NSString *desc) {
callback(code, desc);
}];
} fail:^(int code, NSString *desc) {
callback(code, desc);
}];
}
#pragma mark - TUIInvitedActionProtocal
- (void)acceptCalling {
[self handleStopAudio];
[[TRTCCalling shareInstance] accept];
[self.callingView acceptCalling];
[self startTimer];
[self enableAutoLockScreen:NO];
}
- (void)refuseCalling {
[[TRTCCalling shareInstance] reject];
[self.callingView refuseCalling];
[self handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_DECLINE];
[self handleCallEnd];
}
- (void)hangupCalling {
[[TRTCCalling shareInstance] hangup];
[self handleCallEvent:TUICallingEventCallEnd message:EVENT_CALL_HANG_UP];
[self handleCallEnd];
}
#pragma mark - TRTCCallingDelegate
-(void)onError:(int)code msg:(NSString * _Nullable)msg {
NSLog(@"onError: code %d, msg %@", code, msg);
NSString *toast = [NSString stringWithFormat:@"Error code: %d, Message: %@", code, msg];
if (code == ERR_ROOM_ENTER_FAIL) {
[self makeToast:toast duration:3 position:TUICSToastPositionCenter];
} else if (code != ERR_INVALID_PARAMETERS) {
[self makeToast:toast];
}
[self handleCallEvent:TUICallingEventCallFailed message:msg];
}
- (void)onNetworkQuality:(TRTCQualityInfo *)localQuality
remoteQuality:(NSArray<TRTCQualityInfo *> *)remoteQuality {
if (!self.callingView) {
return;
}
}
- (void)onSwitchToAudio:(BOOL)success
message:(NSString *)message {
if (success) {
self.currentCallingType = TUICallingTypeAudio;
[self.callingView switchToAudio];
}
if (message && message.length > 0) {
[self.callingView makeToast:message];
}
}
- (void)onInvited:(NSString *)sponsor
userIds:(NSArray<NSString *> *)userIDs
isFromGroup:(BOOL)isFromGroup
callType:(CallType)callType {
NSLog(@"log: onInvited sponsor:%@ userIds:%@", sponsor, userIDs);
if (![TUICommonUtil checkArrayValid:userIDs]) {
return;
}
if (self.listener && [self.listener respondsToSelector:@selector(shouldShowOnCallView)]) {
if (![self.listener shouldShowOnCallView]) {
[[TRTCCalling shareInstance] lineBusy];
[self onLineBusy:@""]; // 仅仅提示用户忙线不做calling处理
return;
}
}
self.currentCallingRole = TTUICallingRoleCalled;
self.currentCallingType = [self transformCallType:callType];
if ([self checkAuthorizationStatusIsDenied]) {
return;
}
NSMutableArray *userArray = [NSMutableArray arrayWithArray:userIDs];
[userArray addObject:sponsor];
self.userIDs = [userArray copy];
if (!isFromGroup && [userArray containsObject:sponsor]) {
[userArray removeObject:sponsor];
}
if (userArray.count >= 2 || isFromGroup) {
if (!self.currentUserId) {
return;
}
[self initCallingViewIsGroup:YES];
[self callStartWithUserIDs:self.userIDs type:[self transformCallType:callType] role:TTUICallingRoleCalled];
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[[self currentUserId]] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
if (infoList.count == 0) {
return;
}
[weakSelf.callingView setCurrentUser:[weakSelf covertUser:[infoList firstObject]]];
[weakSelf refreshCallingViewWithUserIDs:userIDs sponsor:sponsor];
} fail:^(int code, NSString *desc) {
NSLog(@"OnInvited getUsersInfo: code %d, msg %@", code, desc);
}];
} else {
[self initCallingViewIsGroup:NO];
[self callStartWithUserIDs:self.userIDs type:[self transformCallType:callType] role:TTUICallingRoleCalled];
[self refreshCallingViewWithUserIDs:[userArray copy] sponsor:sponsor]; }
}
- (void)initCallingViewIsGroup:(BOOL)isGroup {
TUICallingBaseView *callingView = nil;
BOOL isCallee = (self.currentCallingRole == TTUICallingRoleCalled);
BOOL isVideo = (self.currentCallingType == TUICallingTypeVideo);
if (isGroup) {
callingView = (TUICallingBaseView *)[[TUIGroupCallingView alloc] initWithIsVideo:isVideo isCallee:isCallee];
} else {
callingView = (TUICallingBaseView *)[[TUICallingView alloc] initWithIsVideo:isVideo isCallee:isCallee];
}
callingView.actionDelegate = self;
self.callingView = callingView;
}
- (void)refreshCallingViewWithUserIDs:(NSArray<NSString *> *)userIDs sponsor:(NSString *)sponsor {
// 查询用户信息调用IM
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[sponsor] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *curUserInfo = [infoList firstObject];
if (!curUserInfo) return;
[weakSelf configCallViewWithUserIDs:userIDs sponsor:[weakSelf covertUser:curUserInfo isEnter:true]];
} fail:nil];
}
- (void)onGroupCallInviteeListUpdate:(NSArray *)userIds {
NSLog(@"log: onGroupCallInviteeListUpdate userIds:%@", userIds);
}
- (void)onUserEnter:(NSString *)uid {
NSLog(@"log: onUserEnter: %@", uid);
[self handleStopAudio];
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[uid] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *userInfo = [infoList firstObject];
if (!userInfo) return;
[weakSelf startTimer];
[weakSelf enableAutoLockScreen:NO];
CallUserModel *userModel = [weakSelf covertUser:userInfo];
[weakSelf.callingView enterUser:userModel];
} fail:nil];
}
- (void)onUserLeave:(NSString *)uid {
NSLog(@"log: onUserLeave: %@", uid);
[self removeUserFromCallVC:uid removeReason:TUICallingUserRemoveReasonLeave];
}
- (void)onReject:(NSString *)uid {
NSLog(@"log: onReject: %@", uid);
[self removeUserFromCallVC:uid removeReason:TUICallingUserRemoveReasonReject];
}
- (void)onNoResp:(NSString *)uid {
NSLog(@"log: onNoResp: %@", uid);
[self removeUserFromCallVC:uid removeReason:TUICallingUserRemoveReasonNoresp];
}
- (void)onLineBusy:(NSString *)uid {
NSLog(@"log: onLineBusy: %@", uid);
[self removeUserFromCallVC:uid removeReason:TUICallingUserRemoveReasonBusy];
}
- (void)onCallingCancel:(NSString *)uid {
NSLog(@"log: onCallingCancel: %@", uid);
[self makeToast:TUICallingLocalize(@"Demo.TRTC.calling.callingcancel") uid:uid];
[self handleCallEnd];
[self handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_CNACEL];
}
- (void)onCallingTimeOut {
NSLog(@"log: onCallingTimeOut");
[self makeToast:TUICallingLocalize(@"Demo.TRTC.calling.callingtimeout")];
[self handleCallEnd];
[self handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_TIMEOUT];
}
- (void)onCallEnd {
NSLog(@"onCallEnd \n %s", __FUNCTION__);
[self handleCallEnd];
[self handleCallEvent:TUICallingEventCallEnd message:EVENT_CALL_HANG_UP];
}
- (void)onUserAudioAvailable:(NSString *)uid available:(BOOL)available {
NSLog(@"log: onUserAudioAvailable: %@, available: %d",uid, available);
if (self.callingView) {
CallUserModel *userModel = [self.callingView getUserById:uid];
if (userModel) {
userModel.isEnter = YES;
userModel.isAudioAvaliable = available;
[self.callingView updateUser:userModel animated:NO];
}
}
}
- (void)onUserVoiceVolume:(NSString *)uid volume:(UInt32)volume {
if (!self.callingView) return;
CallUserModel *user = [self.callingView getUserById:uid];
if (user) {
CallUserModel *newUser = user;
newUser.isEnter = YES;
newUser.volume = (CGFloat)volume / 100;
[self.callingView updateUserVolume:newUser];
}
}
- (void)onUserVideoAvailable:(NSString *)uid available:(BOOL)available {
NSLog(@"log: onUserLeave: %@", uid);
if (self.callingView) {
CallUserModel *userModel = [self.callingView getUserById:uid];
if (userModel) {
userModel.isEnter = YES;
userModel.isVideoAvaliable = available;
[self.callingView updateUser:userModel animated:NO];
} else {
[[V2TIMManager sharedInstance] getUsersInfo:@[uid] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *userInfo = [infoList firstObject];
CallUserModel *newUser = [self covertUser:userInfo];
newUser.isVideoAvaliable = available;
[self.callingView enterUser:newUser];
} fail:nil];
}
}
}
- (void)removeUserFromCallVC:(NSString *)uid removeReason:(TUICallingUserRemoveReason)removeReason {
if (!self.callingView) return;
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[uid] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *userInfo = [infoList firstObject];
if (!userInfo) return;
CallUserModel *callUserModel = [weakSelf covertUser:userInfo];
[weakSelf.callingView leaveUser:callUserModel];
NSString *toast = @"";
switch (removeReason) {
case TUICallingUserRemoveReasonReject:
if (![TRTCCalling shareInstance].isBeingCalled) {
toast = TUICallingLocalize(@"Demo.TRTC.calling.callingrefuse");
}
[weakSelf handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_HANG_UP];
break;
case TUICallingUserRemoveReasonNoresp:
toast = TUICallingLocalize(@"Demo.TRTC.calling.callingnoresponse");
[weakSelf handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_NO_RESP];
break;
case TUICallingUserRemoveReasonBusy:
toast = TUICallingLocalize(@"Demo.TRTC.calling.callingbusy");
[weakSelf handleCallEvent:TUICallingEventCallFailed message:EVENT_CALL_LINE_BUSY];
break;
default:
break;
}
if (toast && toast.length > 0) {
NSString *userStr = callUserModel.name ?: callUserModel.userId;
toast = [NSString stringWithFormat:@"%@ %@", userStr, toast];
[weakSelf makeToast:toast];
}
} fail:nil];
}
- (void)configCallViewWithUserIDs:(NSArray<NSString *> *)userIDs sponsor:(CallUserModel *)sponsor {
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:userIDs succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
NSMutableArray <CallUserModel *> *modleList = [NSMutableArray array];
for (V2TIMUserFullInfo *model in infoList) {
[modleList addObject:[weakSelf covertUser:model]];
}
if (sponsor) {
[modleList addObject:sponsor];
}
[weakSelf.callingView configViewWithUserList:[modleList copy] sponsor:sponsor];
} fail:nil];
}
#pragma mark - Private method
- (void)makeToast:(NSString *)toast uid:(NSString *)uid {
if (uid && uid.length > 0) {
__weak typeof(self) weakSelf = self;
[[V2TIMManager sharedInstance] getUsersInfo:@[uid] succ:^(NSArray<V2TIMUserFullInfo *> *infoList) {
V2TIMUserFullInfo *userFullInfo = [infoList firstObject];
NSString *toastStr = [NSString stringWithFormat:@"%@ %@", userFullInfo.nickName ?: userFullInfo.userID, toast];
[weakSelf makeToast:toastStr duration:3 position:nil];
} fail:nil];
return;
}
[self makeToast:toast duration:3 position:nil];
}
- (void)makeToast:(NSString *)toast {
[self makeToast:toast duration:3 position:nil];
}
- (void)makeToast:(NSString *)toast duration:(NSTimeInterval)duration position:(id)position {
if (!toast || toast.length <= 0) return;
if (self.callingView) {
[self.callingView makeToast:toast duration:duration position:position];
} else {
[[TUICommonUtil getRootWindow] makeToast:toast duration:duration position:position];
}
}
- (NSString *)currentUserId {
return [[V2TIMManager sharedInstance] getLoginUser];
}
- (CallType)transformCallingType:(TUICallingType)type {
CallType callType = CallType_Unknown;
switch (type) {
case TUICallingTypeVideo:
callType = CallType_Video;
break;
case TUICallingTypeAudio:
default:
callType = CallType_Audio;
break;
}
return callType;
}
- (TUICallingType)transformCallType:(CallType)type {
TUICallingType callingType = TUICallingTypeAudio;
if (type == CallType_Video) {
callingType = TUICallingTypeVideo;
}
return callingType;
}
- (CallUserModel *)covertUser:(V2TIMUserFullInfo *)user {
return [self covertUser:user volume:0 isEnter:NO];
}
- (CallUserModel *)covertUser:(V2TIMUserFullInfo *)user isEnter:(BOOL)isEnter {
return [self covertUser:user volume:0 isEnter:isEnter];
}
- (CallUserModel *)covertUser:(V2TIMUserFullInfo *)user volume:(NSUInteger)volume isEnter:(BOOL)isEnter {
CallUserModel *dstUser = [[CallUserModel alloc] init];
dstUser.name = user.nickName;
dstUser.avatar = user.faceURL;
dstUser.userId = user.userID;
dstUser.isEnter = isEnter ? YES : NO;
dstUser.volume = (CGFloat)volume / 100.0f;
CallUserModel *oldUser = [self.callingView getUserById:user.userID];
if (oldUser) {
dstUser.isVideoAvaliable = oldUser.isVideoAvaliable;
}
return dstUser;
}
- (BOOL)checkAuthorizationStatusIsDenied {
AVAuthorizationStatus statusAudio = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
AVAuthorizationStatus statusVideo = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (statusAudio == AVAuthorizationStatusDenied) {
[[TUICommonUtil getRootWindow] makeToast:TUICallingLocalize(@"Demo.TRTC.Calling.failedtogetmicrophonepermission")];
return YES;
}
if ((self.currentCallingType == TUICallingTypeVideo) && (statusVideo == AVAuthorizationStatusDenied)) {
[[TUICommonUtil getRootWindow] makeToast:TUICallingLocalize(@"Demo.TRTC.Calling.failedtogetcamerapermission")];
return YES;
}
return NO;
}
- (void)startTimer {
if (self.timerName.length) return;
[self handleCallEvent:TUICallingEventCallSucceed message:EVENT_CALL_SUCCEED];
[self handleCallEvent:TUICallingEventCallStart message:EVENT_CALL_START];
self.totalTime = 0;
NSTimeInterval interval = 1.0;
__weak typeof(self) weakSelf = self;
self.timerName = [TRTCGCDTimer timerTask:^{
self.totalTime += (NSInteger)interval;
NSString *minutes = [NSString stringWithFormat:@"%@%ld", (weakSelf.totalTime / 60 < 10) ? @"0" : @"" , (NSInteger)(self.totalTime / 60)];
NSString *seconds = [NSString stringWithFormat:@"%@%ld", (weakSelf.totalTime % 60 < 10) ? @"0" : @"" , weakSelf.totalTime % 60];
[weakSelf.callingView setCallingTimeStr:[NSString stringWithFormat:@"%@ : %@", minutes, seconds]];
} start:0 interval:interval repeats:YES async:NO];
}
- (void)setUserIDs:(NSArray<NSString *> *)userIDs {
NSMutableArray *userIdArray = [NSMutableArray arrayWithArray:userIDs];
[userIDs enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isEqualToString:[self currentUserId]]) {
[userIdArray removeObject:obj];
}
}];
_userIDs = [userIdArray copy];
}
@end