diff --git a/plugin.xml b/plugin.xml index c42209f..afc7d3d 100644 --- a/plugin.xml +++ b/plugin.xml @@ -20,128 +20,62 @@ - - - ---> + + - - - - - - - - - - - - - - - - - - - + + - + + - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - - + + - - - + + - - - - - - - - - - - - + - - - - + + + + + + + - + + @@ -158,8 +92,8 @@ - -用户没有允许需要的权限,加入通话失败 + + 用户没有允许需要的权限,加入通话失败 基础功能 语音通话 双人/多人语音通话、包含静音/免提等功能 @@ -211,7 +145,7 @@ - + @@ -258,7 +192,7 @@ - + diff --git a/src/android/java/com/tencent/trtc/CordovaEventKit.java b/src/android/java/com/tencent/trtc/CordovaEventKit.java index 8af6b43..6ff1c90 100644 --- a/src/android/java/com/tencent/trtc/CordovaEventKit.java +++ b/src/android/java/com/tencent/trtc/CordovaEventKit.java @@ -17,6 +17,7 @@ public class CordovaEventKit { } public static void init(CordovaPlugin plugin){ + Log.d(TAG, "init"); if(CordovaEventKit.kit == null){ CordovaEventKit.kit = new CordovaEventKit(plugin); } diff --git a/src/android/java/com/tencent/trtc/CustomVideoView.java b/src/android/java/com/tencent/trtc/CustomVideoView.java index 286f6e5..0a62564 100644 --- a/src/android/java/com/tencent/trtc/CustomVideoView.java +++ b/src/android/java/com/tencent/trtc/CustomVideoView.java @@ -69,7 +69,7 @@ public class CustomVideoView extends RelativeLayout { Log.d(TAG,"TRTC - changeUser: main?:"+mainView+",alwaysHide?:"+alwaysHide+",user:" + (userInfo == null ? null : userInfo.getPersonid())); this.setBackgroundColor(Color.TRANSPARENT); if(userInfo == null){ - setVisibility(View.GONE);; + setVisibility(View.GONE); }else { setVisibility(alwaysHide?INVISIBLE:VISIBLE); } @@ -88,7 +88,9 @@ public class CustomVideoView extends RelativeLayout { mTRTCCloud.setRemoteRenderParams(this.userInfo.getPersonid(),mainView ? TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG : TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_SUB,params); try { - Thread.sleep(1000); + if(this.userInfo.isShareUser()){ + Thread.sleep(1000); + } } catch (InterruptedException e) { e.printStackTrace(); } @@ -133,12 +135,14 @@ public class CustomVideoView extends RelativeLayout { } public CustomVideoView setMainView(boolean mainView) { + Log.d(TAG,"TRTC - setMainView mainView:"+mainView); if(this.mTRTCCloud == null){ this.mTRTCCloud = TRTCCloud.sharedInstance(mContext); } this.mainView = mainView; if(!mainView){ Events.addListener("subview.always.hide",(extra)->{ + Log.d(TAG,"TRTC - event listener (subview.always.hide):"+extra); this.alwaysHide = extra.getBoolean("alwaysHide",false); if(this.alwaysHide){ this.setVisibility(INVISIBLE); @@ -161,6 +165,7 @@ public class CustomVideoView extends RelativeLayout { }); } Events.addListener("userinfo.update",(extra) -> { + Log.d(TAG,"TRTC - event listener (userinfo.update):"+extra + ",userinfo:"+this.userInfo); if(this.userInfo !=null && !this.userInfo.isLocal() && extra.getString("userId").equals(this.userInfo.getPersonid())){ this.userInfo.setDisplayName(extra.getString("displayName")); this.titleView.setText(this.userInfo.getDisplayName() + (this.userInfo.isShareUser() ? "的屏幕分享": "")); diff --git a/src/android/java/com/tencent/trtc/videocall/UserInfo.java b/src/android/java/com/tencent/trtc/videocall/UserInfo.java index 9527f43..8149d07 100644 --- a/src/android/java/com/tencent/trtc/videocall/UserInfo.java +++ b/src/android/java/com/tencent/trtc/videocall/UserInfo.java @@ -68,4 +68,14 @@ public class UserInfo { } return false; } + + @Override + public String toString() { + return "UserInfo{" + + "personid='" + personid + '\'' + + ", displayName='" + displayName + '\'' + + ", local=" + local + + ", frontCamera=" + frontCamera + + '}'; + } } diff --git a/src/android/java/com/tencent/trtc/videocall/VideoCallingActivity.java b/src/android/java/com/tencent/trtc/videocall/VideoCallingActivity.java index a598278..380e32d 100644 --- a/src/android/java/com/tencent/trtc/videocall/VideoCallingActivity.java +++ b/src/android/java/com/tencent/trtc/videocall/VideoCallingActivity.java @@ -347,6 +347,7 @@ public class VideoCallingActivity extends TRTCBaseActivity implements View.OnCli @Override public void onUserVideoAvailable(String userId, boolean available) { + super.onUserVideoAvailable(userId, available); Log.d(TAG, "onUserVideoAvailable userId " + userId + ", mUserCount " + mUserCount + ",available " + available); UserInfo info = new UserInfo().setPersonid(userId); int index = mUserList.indexOf(info); diff --git a/src/ios/CordovaEventKit.h b/src/ios/CordovaEventKit.h new file mode 100644 index 0000000..f743900 --- /dev/null +++ b/src/ios/CordovaEventKit.h @@ -0,0 +1,22 @@ +// +// CordovaEventKit.h +// shuto-cne +// +// Created by 范大德 on 2022/3/18. +// +#import + +#ifndef CordovaEventKit_h +#define CordovaEventKit_h + + +#endif /* CordovaEventKit_h */ +@interface CordovaEventKit +{} ++ (void)init: (CDVPlugin*)plugin; + ++ (void) fireEvent:(NSString*)event obj:(NSDictionary*) obj; + ++ (void) fireEvent:(NSString*) event msg:(NSString*) msg; + +@end diff --git a/src/ios/CordovaEventKit.m b/src/ios/CordovaEventKit.m new file mode 100644 index 0000000..4e09595 --- /dev/null +++ b/src/ios/CordovaEventKit.m @@ -0,0 +1,71 @@ +// +// CordovaEventKit.m +// 触发Cordova事件 +// +// Created by 范大德 on 2022/3/18. +// +#import + +#import +#import "CordovaEventKit.h" +@interface CordovaEventKit() +{} +@end +@implementation CordovaEventKit + +static CDVPlugin* cdvPlugin; + ++ (void)init: (CDVPlugin*)plugin{ + cdvPlugin = plugin; +} + ++ (void) fireEvent:(NSString*)event obj:(NSDictionary*) obj{ + NSString* jsonData = [self toJSON:obj]; + [CordovaEventKit fireEvent:event msg:jsonData]; +} + ++ (void) fireEvent:(NSString*) event msg:(NSString*) msg{ + NSLog(@"TRTC - CordovaEventKit::fireEvent --- event:%@,msg:%@",event,msg); + + if (cdvPlugin == nil || event == nil || msg == nil) { + NSLog(@"TRTC - CordovaEventKit::fireEvent --- cdvPlugin%@,event:%@,msg:%@",cdvPlugin,event,msg); + return; + } + event = [event stringByReplacingOccurrencesOfString:@"\\" withString:@"_"]; + + NSString* js = [[NSString alloc] initWithFormat:@"window.cordova.plugin.trtc.fireEvent('%@',%@)", event, msg]; + dispatch_async(dispatch_get_main_queue(), ^{ + [cdvPlugin.commandDelegate evalJs:js]; + }); +} + ++(NSString*) toJSON:(NSDictionary*)obj{ + NSError *error = nil; + NSData *jsonData = nil; + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + [obj enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) { + NSString *keyString = nil; + NSString *valueString = nil; + if ([key isKindOfClass:[NSString class]]) { + keyString = key; + }else{ + keyString = [NSString stringWithFormat:@"%@",key]; + } + + if ([obj isKindOfClass:[NSString class]]) { + valueString = obj; + }else{ + valueString = [NSString stringWithFormat:@"%@",obj]; + } + + [dict setObject:valueString forKey:keyString]; + }]; + jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:&error]; + if ([jsonData length] == 0 || error != nil) { + return nil; + } + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return jsonString; +} + +@end diff --git a/src/ios/Events.h b/src/ios/Events.h new file mode 100644 index 0000000..da5ffd9 --- /dev/null +++ b/src/ios/Events.h @@ -0,0 +1,22 @@ +// +// Events.h +// shuto-cne +// +// Created by 范大德 on 2022/3/17. +// + +#ifndef Events_h +#define Events_h + + +#endif /* Events_h */ + +#import "Listener.h" + +@interface Events +{} ++ (void)fireEvent: (NSString*)event; ++ (void)fireEvent: (NSString*)event extra:(NSDictionary*)extra; ++ (void)addListener: (NSString*)event listener:(Listener*)listener; ++ (void)removeListener: (NSString*)event listener:(Listener*)listener; +@end diff --git a/src/ios/Events.m b/src/ios/Events.m new file mode 100644 index 0000000..59fb608 --- /dev/null +++ b/src/ios/Events.m @@ -0,0 +1,64 @@ +// +// Events.m +// 插件中事件流转 +// +// Created by 范大德 on 2022/3/17. +// + +#import +#import "Events.h" +@interface Events() +{} +@end +@implementation Events + +static NSString* PREFIX = @"com.tencent.trtc.event"; +static NSMutableDictionary*> *events = nil; + ++ (void)fireEvent: (NSString*)event{ + [Events fireEvent: nil]; +} ++ (void)fireEvent: (NSString*)event extra:(NSDictionary*)extra{ + [Events init]; + NSLog(@"TRTC - Events::fireEvent --- event:%@,extra:%@",event,extra); + NSMutableOrderedSet* listeners = [self getEventListener:event]; + if(listeners != nil && listeners.count > 0 ){ + for (Listener* listener in listeners) { + NSLog(@"TRTC - Events::fireEvent --- event:%@,listener:%@",event,listener); + [listener on:extra]; + } + } +} ++ (void)addListener: (NSString*)event listener:(Listener*)listener{ + [Events init]; + NSLog(@"TRTC - Events::addListener --- event:%@,listener:%@",event,listener); + NSMutableOrderedSet* listeners = [self getEventListener:event]; + if(![listeners containsObject:listener]){ + [listeners addObject:listener]; + } +} ++ (void)removeListener: (NSString*)event listener:(Listener*)listener{ + [Events init]; + NSLog(@"TRTC - Events::removeListener --- event:%@,listener:%@",event,listener); + NSMutableOrderedSet* listeners = [self getEventListener:event]; + if([listeners containsObject:listener]){ + [listeners removeObject:listener]; + } +} + ++ (void)init{ + if( events == nil){ + events = [NSMutableDictionary dictionary]; + } +} ++ (NSMutableOrderedSet*) getEventListener: (NSString*)event{ + [Events init]; + NSString* key = [[NSString alloc] initWithFormat:@"%@%@", PREFIX, event ]; + NSMutableOrderedSet* listeners =[events valueForKey:key]; + if(listeners == nil){ + listeners = [[NSMutableOrderedSet alloc] init]; + [events setObject:listeners forKey:key]; + } + return [events valueForKey:key]; +} +@end diff --git a/src/ios/Listener.h b/src/ios/Listener.h new file mode 100644 index 0000000..9ce0c35 --- /dev/null +++ b/src/ios/Listener.h @@ -0,0 +1,16 @@ +// +// Listener.h +// shuto-cne +// +// Created by 范大德 on 2022/3/17. +// + +#ifndef Listener_h +#define Listener_h + +#endif /* Listener_h */ +@interface Listener:NSObject +{} +- (instancetype)init; +- (void)on: (NSDictionary*)extra; +@end diff --git a/src/ios/Listener.m b/src/ios/Listener.m new file mode 100644 index 0000000..6264930 --- /dev/null +++ b/src/ios/Listener.m @@ -0,0 +1,21 @@ +// +// Listener.m +// shuto-cne +// +// Created by 范大德 on 2022/3/30. +// + +#import +#import "Listener.h" +@interface Listener() +{} +- (instancetype)init; +- (void)on: (NSDictionary*)extra; +@end + +@implementation Listener +- (instancetype)init{ + return self; +} +- (void)on: (NSDictionary*)extra{} +@end diff --git a/src/ios/Trtc/Info.plist b/src/ios/Trtc/Info.plist deleted file mode 100644 index 49a2d21..0000000 --- a/src/ios/Trtc/Info.plist +++ /dev/null @@ -1,73 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleURLTypes - - - CFBundleTypeRole - Editor - CFBundleURLName - trtcdayisheng - CFBundleURLSchemes - - trtcdayisheng - - - - CFBundleVersion - 1 - LSApplicationCategoryType - - LSRequiresIPhoneOS - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - NSCameraUsageDescription - 请点击“好”以允许访问。 - - NSMicrophoneUsageDescription - 请点击“好”以允许访问。 - - UIBackgroundModes - - audio - - UIMainStoryboardFile - Main - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/src/ios/Trtc/TCLiveConfigDefine.h b/src/ios/Trtc/TCLiveConfigDefine.h deleted file mode 100644 index 0b5a783..0000000 --- a/src/ios/Trtc/TCLiveConfigDefine.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TCLiveConfigDefine.h -// TRTC -// -// Created by xiaowei li on 2018/6/22. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#ifndef TCLiveConfigDefine_h -#define TCLiveConfigDefine_h - -#define Login_Info_Url @"https://xzb.qcloud.com/webrtc/weapp/webrtc_room/get_login_info" //业务后台登录信息拉取,可替换为自己的业务后台 -#define AuthBuffer_Info_Url @"https://xzb.qcloud.com/webrtc/weapp/webrtc_room/get_privatemapkey" -#define Default_Role @"ed640" //用户角色配置画面参数,可在控制台进行配置 https://cloud.tencent.com/document/product/647/17308 -#endif /* TCLiveConfigDefine_h */ diff --git a/src/ios/Trtc/TCLiveJoinRoomViewController.h b/src/ios/Trtc/TCLiveJoinRoomViewController.h deleted file mode 100644 index b5a1a98..0000000 --- a/src/ios/Trtc/TCLiveJoinRoomViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ViewController.h -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -@interface TCLiveJoinRoomViewController : UIViewController - -@property (nonatomic) NSString *defaultRoomId; - -@end - - diff --git a/src/ios/Trtc/TCLiveJoinRoomViewController.m b/src/ios/Trtc/TCLiveJoinRoomViewController.m deleted file mode 100644 index d5ec8ee..0000000 --- a/src/ios/Trtc/TCLiveJoinRoomViewController.m +++ /dev/null @@ -1,112 +0,0 @@ -// -// ViewController.m -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "TCLiveJoinRoomViewController.h" -#import "UIColorEX.h" -#import "TCLiveRoomViewController.h" -#import "UIToastView.h" -#import "TCLiveConfigDefine.h" - -@interface TCLiveJoinRoomViewController () -@property(nonatomic,strong)UITextField *inputTextField; -@property(nonatomic,strong)UIButton *joinRoomBtn; -@property(nonatomic,strong) UIView *botoomLine; -@property(nonatomic,strong) UIImageView *bgImageView; -@end - -@implementation TCLiveJoinRoomViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - self.title = @"视频通话"; - - [self.navigationController.navigationBar setTranslucent:NO]; - - [self.view addSubview:self.bgImageView]; - - [self.view addSubview:self.inputTextField]; - - [self.view addSubview:self.joinRoomBtn]; - -} --(void)viewWillAppear:(BOOL)animated{ - if (self.defaultRoomId) { - self.inputTextField.text = self.defaultRoomId; - } - [super viewWillAppear:animated]; - [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}]; -} --(UIImageView *)bgImageView{ - if (!_bgImageView) { - _bgImageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; - [_bgImageView setImage:[UIImage imageNamed:@"bg.png"]]; - _bgImageView.userInteractionEnabled = YES; - } - return _bgImageView; -} - -- (UIButton *)joinRoomBtn{ - if (!_joinRoomBtn) { - _joinRoomBtn = [[UIButton alloc] initWithFrame:CGRectMake(20, _inputTextField.frame.size.height + _inputTextField.frame.origin.y + 50, self.view.frame.size.width - 40, 50)]; - _joinRoomBtn.layer.cornerRadius = 25; - [_joinRoomBtn setTitle:@"加入房间" forState:UIControlStateNormal]; - _joinRoomBtn.backgroundColor = [UIColor colorWithRGBHex:0x1472fc]; - [_joinRoomBtn addTarget:self action:@selector(joinRoomBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - [_joinRoomBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - } - return _joinRoomBtn; -} -- (UITextField *)inputTextField{ - if (!_inputTextField) { - _inputTextField = [[UITextField alloc] initWithFrame:CGRectMake(5, 20 , self.view.frame.size.width-10, 40)]; - _inputTextField.delegate = self; - _inputTextField.backgroundColor= [UIColor clearColor]; - NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"请输入房间号码" attributes:@{NSForegroundColorAttributeName:[UIColor grayColor]}]; - _inputTextField.attributedPlaceholder = str; - _inputTextField.textColor = [UIColor grayColor]; - _inputTextField.returnKeyType = UIReturnKeyDone; - _inputTextField.keyboardType = UIKeyboardTypeNumberPad; - - _botoomLine = [[UIView alloc] initWithFrame:CGRectMake(0, 40-1, _inputTextField.frame.size.width, 1)]; - _botoomLine.backgroundColor = [UIColor colorWithRGBHex:0x1472fc]; - [_inputTextField addSubview:_botoomLine]; - } - return _inputTextField; -} - -- (void)joinRoomBtnClick:(UIButton *)sender{ - if (self.inputTextField.text.length > 0) { - TCLiveRoomViewController *vc = [[TCLiveRoomViewController alloc] initWithRoomID:self.inputTextField.text role:Default_Role]; - [self.navigationController pushViewController:vc animated:YES]; - } - else{ - [[UIToastView getInstance] showToastWithMessage:@"请输入房间号" toastMode:UIToastShowMode_fail]; - } -} - -// 自动跳转 -//- (void)autoNav:(NSString *)roomId { -// TCLiveRoomViewController *vc = [[TCLiveRoomViewController alloc] initWithRoomID:roomId role:Default_Role]; -// [self.navigationController pushViewController:vc animated:YES]; -//} - - -#pragma mark - UITextFieldDelegate -- (BOOL)textFieldShouldReturn:(UITextField *)textField{ - [textField resignFirstResponder]; - return YES; -} - -- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string -{ - NSCharacterSet *cs = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789"] invertedSet]; - NSString *filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:@""]; - return [string isEqualToString:filtered]; -} -@end diff --git a/src/ios/Trtc/TCLiveRequestManager.h b/src/ios/Trtc/TCLiveRequestManager.h deleted file mode 100644 index 47ebda8..0000000 --- a/src/ios/Trtc/TCLiveRequestManager.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// TCLiveRequestManager.h -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -typedef void (^LiveLoginInfoBlock)(int code); -typedef void (^LiveAuthBufferBlock)(NSDictionary *info); -@interface TCLiveRequestManager : NSObject -@property(nonatomic,assign)int sdkAppID; //app标识,可在实时音视频控制台(https://console.cloud.tencent.com/rav)创建自己的应用生成 -@property(nonatomic,assign)int accountType; //登录实时音视频应用的帐号类型,在控制台创建应用后分配 -@property(nonatomic,strong)NSString *userID; //用户id标识(可由业务后台自己管理) -@property(nonatomic,strong)NSString *userSig; //用于用户鉴权,生成方法https://cloud.tencent.com/document/product/647/17275 (可由业务后台自己管理) -+ (TCLiveRequestManager *)getInstance; -- (void)requestLoginInfo:(LiveLoginInfoBlock)block; -- (void)reqGetAuthBufferInfoWithParams:(NSDictionary *)params block:(LiveAuthBufferBlock)block; -@end diff --git a/src/ios/Trtc/TCLiveRequestManager.m b/src/ios/Trtc/TCLiveRequestManager.m deleted file mode 100644 index 51b7489..0000000 --- a/src/ios/Trtc/TCLiveRequestManager.m +++ /dev/null @@ -1,98 +0,0 @@ -// -// TCLiveRequestManager.m -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "TCLiveRequestManager.h" -#import "UIToastView.h" -#import "TCLiveConfigDefine.h" -@implementation TCLiveRequestManager -+ (TCLiveRequestManager *)getInstance{ - static TCLiveRequestManager *singleTon = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - singleTon = [TCLiveRequestManager new]; - }); - return singleTon; -} - -- (void)requestLoginInfo:(LiveLoginInfoBlock)block{ - NSString *user = [[NSUserDefaults standardUserDefaults] objectForKey:@"TCLIVE_USER"]; - if (user.length == 0) { - user = @""; - } - NSDictionary *params = @{@"userID":user}; - NSMutableURLRequest *request = [self getSendPostRequest:Login_Info_Url body:params];//加备注 - - NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - [sessionConfig setTimeoutIntervalForRequest:30]; - - __weak TCLiveRequestManager *weakself = self; - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig]; - NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { - if (error|| data == nil) { - block(-1); - [[UIToastView getInstance] showToastWithMessage:@"登录请求失败" toastMode:UIToastShowMode_fail]; - } - else{ - //无error data解不出 - NSDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - if (info) { - weakself.sdkAppID = [info[@"sdkAppID"] intValue]; - weakself.accountType = [info[@"accountType"]intValue]; - weakself.userID = info[@"userID"]; - weakself.userSig = info[@"userSig"]; - [[NSUserDefaults standardUserDefaults] setObject:info[@"userID"] forKey:@"TCLIVE_USER"]; - block(0); - } - else{ - block(-1); - [[UIToastView getInstance] showToastWithMessage:@"登录信息解包失败" toastMode:UIToastShowMode_fail]; - } - } - }]; - [task resume]; -} - --(void)reqGetAuthBufferInfoWithParams:(NSDictionary *)params block:(LiveAuthBufferBlock)block{ - NSMutableURLRequest *request = [self getSendPostRequest:AuthBuffer_Info_Url body:params]; - - NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; - [sessionConfig setTimeoutIntervalForRequest:30]; - - NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig]; - NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { - if (error|| data == nil) { - [[UIToastView getInstance] showToastWithMessage:@"获取authBuffer请求失败" toastMode:UIToastShowMode_fail]; - } - else{ - //无error data解不出 - NSDictionary *info = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; - if (info) { - block(info); - } - else{ - [[UIToastView getInstance] showToastWithMessage:@"获取authBuffer解包失败" toastMode:UIToastShowMode_fail]; - } - } - }]; - [task resume]; -} - -- (NSMutableURLRequest *)getSendPostRequest:(NSString *)url body:(NSDictionary *)body{ - - NSData *dataBody = [NSJSONSerialization dataWithJSONObject:body options:NSJSONWritingPrettyPrinted error:nil]; - NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10]; - [request setValue:[NSString stringWithFormat:@"%ld", (long) [dataBody length]] forHTTPHeaderField:@"Content-Length"]; - [request setHTTPMethod:@"POST"]; - [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; - [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"]; - [request setHTTPBody:dataBody]; - - return request; -} -@end - diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.h deleted file mode 100644 index 383bdb1..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// TCLiveChatTableView.h -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import -#import - -@interface TCLiveChatTableView : UITableView -//添加信息到聊天列表 -- (void)addChatMessage:(NSArray *)msgList withContentColor:(UIColor *)contentColor nickColor:(UIColor *)nickColor; -//发送信息 -- (void)sendMessage:(NSString *)message; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.m deleted file mode 100644 index eb15ce5..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableView.m +++ /dev/null @@ -1,177 +0,0 @@ -// -// TCLiveChatTableView.m -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import -#import -#import -#import "TCLiveChatTableView.h" -#import "TCLiveChatTableViewCell.h" -#import "UIColorEX.h" -#import "UIToastView.h" -#import "TCLiveRequestManager.h" - -@interface TCLiveChatTableView () -@property(nonatomic,strong)NSMutableArray *chatMessageList; -@property(nonatomic,strong)UIColor *contentColor; -@property(nonatomic,strong)UIColor *nickColor; -@end - -@implementation TCLiveChatTableView - -- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style{ - if (self = [super initWithFrame:frame style:style]) { - _chatMessageList = [[NSMutableArray alloc] initWithCapacity:1]; - self.delegate = self; - self.dataSource = self; - self.separatorStyle = UITableViewCellSeparatorStyleNone; - self.transform = CGAffineTransformMakeScale(1, -1); - self.layer.cornerRadius = 4; - self.layer.masksToBounds = YES; - self.scrollEnabled = NO; - //设置消息监听 - [[[ILiveSDK getInstance] getTIMManager] setMessageListener:self]; - } - return self; -} - -//接收消息 --(void)onNewMessage:(NSArray *)msgs{ - [self addChatMessage:msgs withContentColor:nil nickColor:nil]; -} -//消息处理 -- (void)addChatMessage:(NSArray *)msgList withContentColor:(UIColor *)contentColor nickColor:(UIColor *)nickColor{ - self.contentColor = contentColor; - self.nickColor = nickColor; - for (id item in msgList) { - [self.chatMessageList insertObject:item atIndex:0]; - } - //过滤非文本消息 - NSMutableArray *tempArr = [NSMutableArray array]; - for (int i = 0; i < msgList.count;i++) { - TIMMessage *msg = msgList[i]; - if (![self isTextMsg:msg]) { - [tempArr addObject:msg]; - } - } - [self.chatMessageList removeObjectsInArray:tempArr]; - - dispatch_async(dispatch_get_main_queue(), ^{ - [self reloadData]; - }); -} -- (BOOL)isTextMsg:(TIMMessage *)msg { - TIMOfflinePushInfo *info = msg.getOfflinePushInfo; - if ([info.ext hasPrefix:@"TEXT"]) { - return YES; - } - int count = [msg elemCount]; - for(int i = 0; i < count; i++) { - TIMElem *elem = [msg getElem:i]; - if ([elem isKindOfClass:[TIMCustomElem class]]){ - if ([((TIMCustomElem*)elem).ext hasPrefix:@"TEXT"]) { - return YES; - } - } - else if ([elem isKindOfClass:[TIMTextElem class]]){ - return YES; - } - } - return NO; -} -//发送消息 -- (void)sendMessage:(NSString *)message{ - //消息组装 - TIMMessage *msge = [[TIMMessage alloc] init]; - TIMCustomElem *textElem = [[TIMCustomElem alloc] init]; - textElem.data = [message dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *descDic = @{@"nickName":[TCLiveRequestManager getInstance].userID}; - NSString *desc = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:descDic options:NSJSONReadingAllowFragments error:nil] encoding:NSUTF8StringEncoding]; - textElem.desc = desc; - textElem.ext = @"TEXT"; - [msge addElem:textElem]; - //调用发送接口 - [[ILiveRoomManager getInstance] sendGroupMessage:msge succ:^{ - NSLog(@"send message succ"); - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"send message fail"); - [[UIToastView getInstance] showToastWithMessage:@"发送消息失败" toastMode:UIToastShowMode_fail]; - }]; - [self addChatMessage:@[msge] withContentColor:nil nickColor:nil]; -} -#pragma mark - UITableViewDelegate - --(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ - TCLiveChatTableViewCell *cell = [self createChatTableViewCell:tableView withIndexPath:indexPath]; - return cell.cellHeight; -} -#pragma mark - UITableViewDataSource - --(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ - return self.chatMessageList.count; -} - --(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ - TCLiveChatTableViewCell *cell = [self createChatTableViewCell:tableView withIndexPath:indexPath]; - return cell; -} -//创建消息cell -- (TCLiveChatTableViewCell *)createChatTableViewCell:(UITableView *)tableView withIndexPath:(NSIndexPath *)indexPath{ - TCLiveChatTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ChatTableviewCell"]; - if (!cell) { - cell = [[TCLiveChatTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ChatTableviewCell"]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.backgroundColor = [UIColor clearColor]; - cell.contentView.transform = CGAffineTransformMakeScale (1,-1); - } - TIMMessage *msg = self.chatMessageList[indexPath.row]; - int count = [msg elemCount]; - for(int i = 0; i < count; i++) { - TIMElem *elem = [msg getElem:i]; - //收到消息展示 - NSMutableAttributedString *msgInfo = [[NSMutableAttributedString alloc] initWithString:@""]; - if([elem isKindOfClass:[TIMTextElem class]]){ - msgInfo = [self getContentWithNick:msg.sender andContentTex:((TIMTextElem *)elem).text]; - [cell setModel:msgInfo]; - break; - } - else if ([elem isKindOfClass:[TIMCustomElem class]]){ - NSString *nick = msg.sender; - NSString *dataStr = [[NSString alloc] initWithData:((TIMCustomElem *)elem).data encoding:NSUTF8StringEncoding]; - NSDictionary *descDic = [NSJSONSerialization JSONObjectWithData:[((TIMCustomElem *)elem).desc dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingAllowFragments error:nil]; - NSString *nickNmae = descDic[@"nickName"]; - if (nickNmae.length > 0) { - nick = nickNmae; - } - msgInfo = [self getContentWithNick:nick andContentTex:dataStr]; - [cell setModel:msgInfo]; - break; - } - } - return cell; -} -- (NSMutableAttributedString *)getContentWithNick:(NSString *)nick andContentTex:(NSString *)contentText{ - NSString *content = [NSString stringWithFormat:@"%@:%@",nick, contentText]; - NSMutableAttributedString *msgInfo = [[NSMutableAttributedString alloc] initWithString:content]; - UIColor *contentColor = [UIColor whiteColor]; - UIColor *nickColor = [UIColor colorWithRGBHex:0xFF4081]; - if (self.contentColor) { - contentColor = self.contentColor; - } - if(self.nickColor){ - nickColor = self.nickColor; - } - [msgInfo addAttribute:NSForegroundColorAttributeName value:contentColor range:[content rangeOfString:contentText]]; - [msgInfo addAttribute:NSForegroundColorAttributeName value:nickColor range:[content rangeOfString:nick]]; - - return msgInfo; -} -//点击事件透传 --(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{ - return nil; -} -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.h deleted file mode 100644 index 8140059..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// TCLiveChatTableViewCell.h -// TRTC -// -// Created by Tencent on 2018/6/8. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -@interface TCLiveChatTableViewCell : UITableViewCell -@property(nonatomic,assign)CGFloat cellHeight; --(void)setModel:(NSMutableAttributedString *)model; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.m deleted file mode 100644 index 79bebde..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveChatTableViewCell.m +++ /dev/null @@ -1,59 +0,0 @@ -// -// TCLiveChatTableViewCell.m -// TRTC -// -// Created by Tencent on 2018/6/8. -// Copyright © 2018年 Tencent. All rights reserved. -// - - -#import "TCLiveChatTableViewCell.h" - -@interface TCLiveChatTableViewCell () -@property(nonatomic,strong) UILabel *contentLabel; -@property(nonatomic,strong) UIView *backMaskView; -@end - -@implementation TCLiveChatTableViewCell - -- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ - if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { - - [self.contentView addSubview:self.backMaskView]; - [_backMaskView addSubview:self.contentLabel]; - } - return self; -} - --(UILabel *)contentLabel{ - if (!_contentLabel) { - _contentLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _contentLabel.backgroundColor = [UIColor clearColor]; - _contentLabel.textAlignment = NSTextAlignmentLeft; - _contentLabel.font = [UIFont systemFontOfSize:13]; - _contentLabel.textColor = [UIColor whiteColor]; - _contentLabel.numberOfLines = 0; - } - return _contentLabel; -} - --(UIView *)backMaskView{ - if (!_backMaskView) { - _backMaskView = [[UIView alloc] initWithFrame:CGRectZero]; - _backMaskView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - _backMaskView.layer.cornerRadius = 10; - _backMaskView.layer.masksToBounds = YES; - } - return _backMaskView; -} - --(void)setModel:(NSMutableAttributedString *)model{ - _contentLabel.attributedText = model; - CGSize size = [_contentLabel sizeThatFits:CGSizeMake(230, 10000)]; - - _contentLabel.frame = CGRectMake(5, 5, size.width, size.height ); - _backMaskView.frame = CGRectMake(5, 5, size.width + 10, size.height + 10); - self.cellHeight = size.height+20; -} - -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.h deleted file mode 100644 index 4e33f53..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// TCLiveRoomViewController.h -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import -#import "TCLiveVideoLayoutView.h" - -@interface TCLiveRoomViewController : UIViewController -//传入roomid(房间号)进入指定房间 设置role配置画面参数 --(instancetype)initWithRoomID:(NSString *)roomid role:(NSString *)role; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.m deleted file mode 100644 index ccd07de..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveRoomViewController.m +++ /dev/null @@ -1,275 +0,0 @@ -// -// TCLiveRoomViewController.m -// TRTC -// -// Created by Tencent on 2018/5/31. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "TCLiveRoomViewController.h" -#import -#import -#import -#import -#import -#import -#import -#import "TCLiveRequestManager.h" -#import "TCLiveVideoControlBar.h" -#import "TCLiveChatTableView.h" -#import "UIToastView.h" - -#define LIVE_VIEW_HEIGHT 370 -#define LIVE_CONTROL_BAR_HEIGHT 70 -#define LIVE_INPUTTEXTFIELD_HEIGHT 40 - -@interface TCLiveRoomViewController () -@property(nonatomic,strong) TCLiveVideoLayoutView *videoLayoutView; -@property(nonatomic,strong) TCLiveVideoControlBar *controlBar; -@property(nonatomic,strong) TCLiveChatTableView *chatTableView; -@property(nonatomic,strong) UITextField *inputTextField; -@property(nonatomic,strong) NSString *roomID; -@property(nonatomic,strong) UIImageView *bgImageView; -@property(nonatomic,strong) NSTimer *logTimer; -@property(nonatomic,strong) NSTimer *heartBeatTimer; -@property(nonatomic,assign) CGRect origInputTextFieldFrame; -@property(nonatomic,assign) CGRect origChatTableViewFrame; -@property(nonatomic,strong) NSString *role; -@end - -@implementation TCLiveRoomViewController - --(instancetype)initWithRoomID:(NSString *)roomid role:(NSString *)role{ - if (self = [super init]) { - self.roomID = roomid; - self.role = role; - } - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - // Do any additional setup after loading the view. - self.title = self.roomID; - [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor]}]; - - [self enterRoom]; - - [self customLeftButton]; - - [self.view addSubview:self.bgImageView]; - - [_bgImageView addSubview:self.videoLayoutView]; - - [_bgImageView addSubview:self.chatTableView]; - - [_bgImageView addSubview:self.controlBar]; - - [_bgImageView addSubview:self.inputTextField]; - - //监听键盘变化 - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; -} --(void)viewWillAppear:(BOOL)animated{ - [super viewWillAppear:animated]; - //导航栏透明化 - [self setNavigationBarTransparent]; - [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; -} - -- (void)viewWillDisappear:(BOOL)animated{ - [super viewWillDisappear:animated]; - [self.navigationController.navigationBar setTranslucent:NO]; - [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; -} -- (void)setNavigationBarTransparent{ - [self.navigationController.navigationBar setTranslucent:YES]; - [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault]; - [self.navigationController.navigationBar setShadowImage:[[UIImage alloc]init]]; - [self.navigationController.navigationBar setBackgroundColor:[UIColor clearColor]]; -} - -- (void)enterRoom{ - [[TCLiveRequestManager getInstance] reqGetAuthBufferInfoWithParams:@{@"roomID":self.roomID,@"userID":[TCLiveRequestManager getInstance].userID} block:^(NSDictionary *info) { - ILiveRoomOption *option = [ILiveRoomOption defaultHostLiveOption]; - option.imOption.imSupport = YES; - option.memberStatusListener = self.videoLayoutView; - option.roomDisconnectListener = self; - option.controlRole = self.role; - option.avOption.privateMapKey = [info[@"privateMapKey"] dataUsingEncoding:NSUTF8StringEncoding]; - - [[ILiveRoomManager getInstance] createRoom:[self.roomID intValue] option:option succ:^{ - NSLog(@"-----> create room succ"); - [[UIToastView getInstance] showToastWithMessage:@"创建房间成功" toastMode:UIToastShowMode_Succ]; - [self.controlBar enableBeauty:YES];//进入房间默认开启美颜 - } failed:^(NSString *module, int errId, NSString *errMsg) { - if(errId == 10021){ - //表示房间已存在直接加入房间 - [[ILiveRoomManager getInstance] joinRoom:[self.roomID intValue] option:option succ:^{ - NSLog(@"-----> join room succ"); - [[UIToastView getInstance] showToastWithMessage:@"加入房间成功" toastMode:UIToastShowMode_Succ]; - [self.controlBar enableBeauty:YES];//进入房间默认开启美颜 - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"-----> join room fail,%@ %d %@",module, errId, errMsg); - [[UIToastView getInstance] showToastWithMessage:errMsg toastMode:UIToastShowMode_fail]; - }]; - } - else{ - NSLog(@"-----> create room fail,%@ %d %@",module, errId, errMsg); - [[UIToastView getInstance] showToastWithMessage:errMsg toastMode:UIToastShowMode_fail]; - } - }]; - }]; - -} - -- (void)customLeftButton{ - UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom]; - backBtn.frame = CGRectMake(0, 0, 44, 44); - [backBtn setImage:[UIImage imageNamed:@"ui_title_arrow_left.png"] forState:UIControlStateNormal]; - [backBtn addTarget:self action:@selector(backBtnClicked:) forControlEvents:UIControlEventTouchUpInside]; - backBtn.frame = CGRectMake(0, 0, 44, 44); - [backBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; - backBtn.imageEdgeInsets = UIEdgeInsetsMake(10, 0, 10, 20); - UIBarButtonItem *item = [[UIBarButtonItem alloc]initWithCustomView:backBtn]; - self.navigationItem.leftBarButtonItem = item; -} - -- (UIImageView *)bgImageView{ - if (!_bgImageView) { - _bgImageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; - [_bgImageView setImage:[UIImage imageNamed:@"bg.png"]]; - _bgImageView.userInteractionEnabled = YES; - } - return _bgImageView; -} - -//视频区域 --(TCLiveVideoLayoutView *)videoLayoutView{ - if (!_videoLayoutView) { - _videoLayoutView = [[TCLiveVideoLayoutView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)]; - } - return _videoLayoutView; -} -//控制bar -- (TCLiveVideoControlBar *)controlBar{ - if (!_controlBar) { - _controlBar = [[TCLiveVideoControlBar alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - LIVE_CONTROL_BAR_HEIGHT, self.view.frame.size.width, LIVE_CONTROL_BAR_HEIGHT)]; - _controlBar.delegate = self; - } - return _controlBar; -} -//消息列表 -- (UITableView *)chatTableView{ - if (!_chatTableView) { - _chatTableView = [[TCLiveChatTableView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - LIVE_CONTROL_BAR_HEIGHT - 400, 250, 400) style:UITableViewStylePlain]; - _chatTableView.backgroundColor = [UIColor clearColor]; - self.origChatTableViewFrame = self.chatTableView.frame; - } - return _chatTableView; -} -//输入框 -- (UITextField *)inputTextField{ - if (!_inputTextField) { - _inputTextField = [[UITextField alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height , self.view.frame.size.width, LIVE_INPUTTEXTFIELD_HEIGHT)]; - _inputTextField.delegate = self; - _inputTextField.backgroundColor= [[UIColor whiteColor] colorWithAlphaComponent:0.9]; - _inputTextField.placeholder = @"请输入内容"; - _inputTextField.returnKeyType = UIReturnKeySend; - self.origInputTextFieldFrame = self.inputTextField.frame; - } - return _inputTextField; -} -//关闭界面退出房间 -- (void)backBtnClicked:(UIButton *)sender{ - [self.navigationController popViewControllerAnimated:YES]; - [[ILiveRoomManager getInstance] quitRoom:^{ - NSLog(@"-----> quit room succ"); - [[UIToastView getInstance] showToastWithMessage:@"退出房间成功" toastMode:UIToastShowMode_Succ]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"-----> quit room fail,%@ %d %@",module, errId, errMsg); - [[UIToastView getInstance] showToastWithMessage:@"退出房间失败" toastMode:UIToastShowMode_fail]; - }]; - [_logTimer invalidate]; - _logTimer = nil; - -} -#pragma mark - ILiveRoomDisconnectListener -- (BOOL)onRoomDisconnect:(int)reason;{ - [self backBtnClicked:nil]; - return YES; -} -#pragma mark - UITextFieldDelegate - -- (BOOL)textFieldShouldReturn:(UITextField *)textField;{ - [textField resignFirstResponder]; - NSString *text = textField.text; - if (text.length > 0) { - [self.chatTableView sendMessage:text]; - textField.text = nil; - } - else{ - return NO; - } - return YES; -} -#pragma mark - TCLiveVideoControlBarDelegate --(void)logBtnClick:(UIButton *)sender{ - if (sender.selected) { - if (!_logTimer) { - [self logUpdate]; - _logTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(logUpdate) userInfo:nil repeats:YES]; - } - } - else{ - [_logTimer invalidate]; - _logTimer = nil; - [_videoLayoutView closeLogView]; - } -} -- (void)chatBtnClick:(UIButton *)sender{ - [self.inputTextField becomeFirstResponder]; -} -- (void)logUpdate{ - QAVContext *avContext = [[ILiveSDK getInstance] getAVContext]; - NSString *qualityStr = [avContext.room getQualityTips]; - [_videoLayoutView showLogView:qualityStr]; -} - -- (void)beautyBtnClick:(UIButton *)sender{ - if (sender.selected) { - [self.videoLayoutView setBeautyLevel:9]; - } - else{ - [self.videoLayoutView setBeautyLevel:0]; - } -} -#pragma mark - 键盘事件 -- (void)keybaordAnimationWithDuration:(CGFloat)duration keyboardOriginY:(CGFloat)keyboardOriginY{ - - __block TCLiveRoomViewController *blockSelf = self; - //作为视图的键盘,弹出动画也是UIViewAnimationOptionCurveEaseIn的方式 - [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ - //text field - if(keyboardOriginY == blockSelf.view.frame.size.height){ - blockSelf.inputTextField.frame = blockSelf.origInputTextFieldFrame; - blockSelf.chatTableView.frame = blockSelf.origChatTableViewFrame; - } - else{ - blockSelf.inputTextField.frame = CGRectMake(blockSelf.inputTextField.frame.origin.x,keyboardOriginY - blockSelf.inputTextField.frame.size.height, blockSelf.inputTextField.frame.size.width, blockSelf.inputTextField.frame.size.height); - blockSelf.chatTableView.frame = CGRectMake(blockSelf.chatTableView.frame.origin.x,keyboardOriginY - blockSelf.chatTableView.frame.size.height - LIVE_INPUTTEXTFIELD_HEIGHT, blockSelf.chatTableView.frame.size.width, blockSelf.chatTableView.frame.size.height); - } - - } completion:nil]; -} -- (void)keyboardWillChangeFrame:(NSNotification *)notify{ - NSDictionary * info = notify.userInfo; - //动画时间 - CGFloat animationDuration = [info[UIKeyboardAnimationDurationUserInfoKey] floatValue]; - //键盘目标位置 - CGRect keyboardAimFrame = [info[UIKeyboardFrameEndUserInfoKey] CGRectValue]; - if ([self.inputTextField isFirstResponder]) { - [self keybaordAnimationWithDuration:animationDuration keyboardOriginY:keyboardAimFrame.origin.y]; - } -} -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.h deleted file mode 100644 index b3a8650..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// UIColorEX.h -// TRTC -// -// Created by Tencent on 2018/6/5. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -@interface UIColor (EX) -+ (UIColor *)colorWithRGBHex: (unsigned int)hex; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.m deleted file mode 100644 index 458f5fc..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIColorEX.m +++ /dev/null @@ -1,25 +0,0 @@ -// -// UIColorEX.m -// TRTC -// -// Created by Tencent on 2018/6/5. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "UIColorEX.h" - -@implementation UIColor (EX) - -+ (UIColor *)colorWithRGBHex: (unsigned int)hex -{ - int r = (hex >> 16) & 0xFF; - int g = (hex >> 8) & 0xFF; - int b = (hex) & 0xFF; - - return [UIColor colorWithRed:r / 255.0f - green:g / 255.0f - blue:b / 255.0f - alpha:1.0f]; -} - -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.h deleted file mode 100644 index 4103160..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.h +++ /dev/null @@ -1,20 +0,0 @@ -// -// UIToastView.h -// TRTC -// -// Created by Tencent on 2018/6/9. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -typedef enum { - UIToastShowMode_Default = 1, - UIToastShowMode_Succ, - UIToastShowMode_fail, -}UIToastShowMode; - -@interface UIToastView : UIView -+ (UIToastView *)getInstance; -- (void)showToastWithMessage:(NSString *)text toastMode:(UIToastShowMode )mode; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.m deleted file mode 100644 index e5d631b..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveUITools/UIToastView.m +++ /dev/null @@ -1,96 +0,0 @@ -// -// UIToastView.m -// TRTC -// -// Created by Tencent on 2018/6/9. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "UIToastView.h" - -#define UITOAST_HEIGHT 30 -#define UITOAST_IMAGE_HEIGHT 15 -@interface UIToastView () -@property(nonatomic,strong)UILabel *toastLabel; -@property(nonatomic,strong)UIImageView *toastImageView; -@end - -@implementation UIToastView - -+ (UIToastView *)getInstance{ - static UIToastView *singleTon = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - singleTon = [UIToastView new]; - }); - return singleTon; -} - --(instancetype)initWithFrame:(CGRect)frame{ - if (self = [super initWithFrame:frame]) { - self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5]; - self.layer.cornerRadius = 4; - self.layer.masksToBounds = YES; - - [self addSubview:self.toastImageView]; - [self addSubview:self.toastLabel]; - } - return self; -} -- (UILabel *)toastLabel{ - if (!_toastLabel) { - _toastLabel = [[UILabel alloc] initWithFrame:CGRectZero]; - _toastLabel.numberOfLines = 1; - _toastLabel.textAlignment = NSTextAlignmentCenter; - _toastLabel.textColor = [UIColor whiteColor]; - _toastLabel.font = [UIFont systemFontOfSize:16]; - } - return _toastLabel; -} - --(UIImageView *)toastImageView{ - if (!_toastImageView) { - _toastImageView = [[UIImageView alloc] initWithFrame:CGRectZero]; - - } - return _toastImageView; -} - -- (void)showToastWithMessage:(NSString *)text toastMode:(UIToastShowMode )mode{ - dispatch_async(dispatch_get_main_queue(), ^{ - UIToastView *view = [UIToastView new]; - CGRect rect = [text boundingRectWithSize:CGSizeMake([UIScreen mainScreen].bounds.size.width - 80, 20) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:16]} context:nil]; - view.frame = CGRectMake(0, 0, rect.size.width + 10 + 20, UITOAST_HEIGHT); - view.toastImageView.frame = CGRectMake(5, 0, UITOAST_IMAGE_HEIGHT, UITOAST_IMAGE_HEIGHT); - view.toastImageView.center = CGPointMake(view.toastImageView.center.x, view.frame.size.height/2); - view.toastLabel.frame = CGRectMake(25, 0, rect.size.width, UITOAST_HEIGHT); - view.toastLabel.text = text; - if (UIToastShowMode_Succ == mode){ - view.toastImageView.image = [UIImage imageNamed:@"ic_toast_success@2x"]; - } - else if(UIToastShowMode_fail == mode){ - view.toastImageView.image = [UIImage imageNamed:@"icon_sign@2x"]; - } - else{ - view.toastImageView.frame = CGRectZero; - view.frame = CGRectMake(0, 0, rect.size.width + 10 , UITOAST_HEIGHT); - view.toastLabel.frame = CGRectMake(5, 0, rect.size.width, UITOAST_HEIGHT); - } - view.center = [[UIApplication sharedApplication] keyWindow].center; - [[[UIApplication sharedApplication] keyWindow] addSubview:view]; - [UIView animateWithDuration:0.5 animations:^{ - view.alpha = 1; - } completion:^(BOOL finished) { - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - [UIView animateWithDuration:0.5 animations:^{ - view.alpha = 0; - } completion:^(BOOL finished) { - [view removeFromSuperview]; - }]; - }); - }]; - }); - -} - -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.h deleted file mode 100644 index 93f1a42..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.h +++ /dev/null @@ -1,34 +0,0 @@ -// -// TCLiveVideoControlBar.h -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import - -@protocol TCLiveVideoControlBarDelegate -@optional -//切换摄像头 -- (void)switchCameraBtnClick:(UIButton *)sender; -//开关美颜 -- (void)beautyBtnClick:(UIButton *)sender; -//开关麦克风 -- (void)voiceBtnClick:(UIButton *)sender; -//展示日志 -- (void)logBtnClick:(UIButton *)sender; -//反馈 -- (void)feedBackBtnClick:(UIButton *)sender; -//切换配置 -- (void)changeRoleBtnClick:(UIButton *)sender; -//聊天 -- (void)chatBtnClick:(UIButton *)sender; -@end - -@interface TCLiveVideoControlBar : UIView -@property(nonatomic,weak)id delegate; -@property(nonatomic,strong) UIButton *logBtn; -- (void)enableLog:(BOOL)endable; -- (void)enableBeauty:(BOOL)enable; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.m deleted file mode 100644 index 0eb7c7d..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoControlBar.m +++ /dev/null @@ -1,298 +0,0 @@ -// -// TCLiveVideoControlBar.m -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - - - -#import "TCLiveVideoControlBar.h" -#import -#import -#import -#import "TCLiveRequestManager.h" -#import "UIToastView.h" -#import "TCLiveRoomViewController.h" - -#define CONTROLBAR_BUTTON_WIDTH 50 - -@interface TCLiveVideoControlBar () -@property(nonatomic,strong) UIButton *chatBtn; -@property(nonatomic,strong) UIButton *switchCamera; -@property(nonatomic,strong) UIButton *beautyBtn; -@property(nonatomic,strong) UIButton *voiceBtn; -@property(nonatomic,strong) UIButton *changeRoleBtn; -@property(nonatomic,strong) UIButton *feedBackBtn; -@end - -@implementation TCLiveVideoControlBar - --(instancetype)initWithFrame:(CGRect)frame -{ - if (self = [super initWithFrame:frame]) { -// [self addSubview:self.chatBtn]; -// [self addSubview:self.beautyBtn]; - [self addSubview:self.voiceBtn]; -// [self addSubview:self.logBtn]; - [self addSubview:self.switchCamera]; -// [self addSubview:self.feedBackBtn]; -// [self addSubview:self.changeRoleBtn]; - self.backgroundColor = [UIColor clearColor]; - } - return self; -} - --(UIButton *)chatBtn{ - if(!_chatBtn){ - _chatBtn = [self createCustomControlBtn:@"聊天" withImage:[UIImage imageNamed:@"chat.png"] selectedImage:nil]; - [_chatBtn addTarget:self action:@selector(chatBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } - _chatBtn.frame = CGRectMake(self.frame.size.width / 2 - CONTROLBAR_BUTTON_WIDTH * 3.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _chatBtn; -} --(UIButton *)switchCamera{ - if (!_switchCamera) { - _switchCamera = [self createCustomControlBtn:@"翻转" withImage:[UIImage imageNamed:@"camera.png"] selectedImage:[UIImage imageNamed:@"camera-gray.png"]]; - [_switchCamera addTarget:self action:@selector(switchCameraClick:) forControlEvents:UIControlEventTouchUpInside]; - } -// _switchCamera.frame = CGRectMake(self.frame.size.width/2 - CONTROLBAR_BUTTON_WIDTH * 2.5,0,CONTROLBAR_BUTTON_WIDTH,self.frame.size.height); - _switchCamera.frame = CGRectMake(self.frame.size.width/2 - CONTROLBAR_BUTTON_WIDTH * 1.5,0,CONTROLBAR_BUTTON_WIDTH,self.frame.size.height); - return _switchCamera; -} - -- (UIButton *)beautyBtn{ - if (!_beautyBtn) { - _beautyBtn = [self createCustomControlBtn:@"美颜" withImage:[UIImage imageNamed:@"beauty.png"] selectedImage:[UIImage imageNamed:@"beauty-dis.png"]]; - [_beautyBtn addTarget:self action:@selector(beautyBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } - _beautyBtn.frame = CGRectMake(self.frame.size.width/2 - CONTROLBAR_BUTTON_WIDTH *1.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _beautyBtn; -} - -- (UIButton *)voiceBtn{ - if (!_voiceBtn) { - _voiceBtn = [self createCustomControlBtn:@"声音" withImage:[UIImage imageNamed:@"mic-dis.png"] selectedImage:[UIImage imageNamed:@"mic.png"]]; - [_voiceBtn addTarget:self action:@selector(voiceBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } -// _voiceBtn.frame = CGRectMake(self.frame.size.width/2 - CONTROLBAR_BUTTON_WIDTH * 0.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - _voiceBtn.frame = CGRectMake(self.frame.size.width/2 + CONTROLBAR_BUTTON_WIDTH * 0.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _voiceBtn; -} - --(UIButton *)changeRoleBtn{ - if (!_changeRoleBtn) { - _changeRoleBtn = [self createCustomControlBtn:@"配置" withImage:[UIImage imageNamed:@"role.png"] selectedImage:[UIImage imageNamed:@"role.png"]]; - [_changeRoleBtn addTarget:self action:@selector(changeRoleBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } - _changeRoleBtn.frame = CGRectMake(self.frame.size.width/2 + CONTROLBAR_BUTTON_WIDTH * 0.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _changeRoleBtn; -} - -- (UIButton *)feedBackBtn{ - if (!_feedBackBtn) { - _feedBackBtn = [self createCustomControlBtn:@"反馈" withImage:[UIImage imageNamed:@"feedback.png"] selectedImage:[UIImage imageNamed:@"feedback.png"]]; - [_feedBackBtn addTarget:self action:@selector(feedBackBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } - _feedBackBtn.frame = CGRectMake(self.frame.size.width/2 + CONTROLBAR_BUTTON_WIDTH * 1.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _feedBackBtn; -} - -- (UIButton *)logBtn{ - if (!_logBtn) { - _logBtn = [self createCustomControlBtn:@"信息" withImage:[UIImage imageNamed:@"log.png"] selectedImage:[UIImage imageNamed:@"log2.png"]]; - [_logBtn addTarget:self action:@selector(logBtnClick:) forControlEvents:UIControlEventTouchUpInside]; - } - _logBtn.frame = CGRectMake(self.frame.size.width/2 + CONTROLBAR_BUTTON_WIDTH * 2.5, 0, CONTROLBAR_BUTTON_WIDTH, self.frame.size.height); - return _logBtn; -} - -- (UIButton *)createCustomControlBtn:(NSString *)wording withImage:(UIImage *)image selectedImage:(UIImage *)highlightImage{ - UIButton *customButton = [[UIButton alloc] initWithFrame:CGRectZero]; - [customButton setTitle:wording forState:UIControlStateNormal]; - customButton.titleLabel.font = [UIFont systemFontOfSize:11]; - [customButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; - [customButton setImage:image forState:UIControlStateNormal]; - [customButton setImage:highlightImage forState:UIControlStateSelected]; - CGFloat imageHeight = image.size.height; - CGFloat imageWidth = image.size.width; - [customButton setTitleEdgeInsets:UIEdgeInsetsMake(15, -60, -15, 0)]; - [customButton setImageEdgeInsets:UIEdgeInsetsMake(10, 10, self.frame.size.height - (CONTROLBAR_BUTTON_WIDTH - 20)/imageWidth *imageHeight -10, 10)]; - return customButton; -} -#pragma mark - Handle Event -//聊天按钮 -- (void)chatBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - if ([_delegate respondsToSelector:@selector(chatBtnClick:)]) { - [_delegate chatBtnClick:sender]; - } -} -//切换摄像头 -- (void)switchCameraClick:(UIButton *)sender{ - ILiveFrameDispatcher *frameDispatcher = [[ILiveRoomManager getInstance] getFrameDispatcher]; - ILiveRenderView *renderView = [frameDispatcher getRenderView:[TCLiveRequestManager getInstance].userID srcType:QAVVIDEO_SRC_TYPE_CAMERA]; - if (!sender.selected) { - sender.selected = YES; - renderView.isMirror = NO; - } - else{ - sender.selected = NO; - renderView.isMirror = YES; - } - [[ILiveRoomManager getInstance] switchCamera:^{ - NSLog(@"switch camera succ"); - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"switch camera fail"); - [[UIToastView getInstance] showToastWithMessage:@"切换摄像头失败" toastMode:UIToastShowMode_fail]; - }]; - if ([_delegate respondsToSelector:@selector(switchCameraClick:)]) { - [_delegate switchCameraBtnClick:sender]; - } -} -//美颜 -- (void)beautyBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - if ([_delegate respondsToSelector:@selector(beautyBtnClick:)]) { - [_delegate beautyBtnClick:sender]; - } -} -- (void)enableBeauty:(BOOL)enable{ - if (enable) { - _beautyBtn.selected = YES; - } - else{ - _beautyBtn.selected = NO; - } - if ([_delegate respondsToSelector:@selector(beautyBtnClick:)]) { - [_delegate beautyBtnClick:_beautyBtn]; - } -} -//语音开关 -- (void)voiceBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - [[ILiveRoomManager getInstance] enableMic:!sender.selected succ:^{ - NSLog(@"enable mic succ"); - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"enable mic fail"); - [[UIToastView getInstance] showToastWithMessage:@"关麦失败" toastMode:UIToastShowMode_fail]; - }]; - if ([_delegate respondsToSelector:@selector(voiceBtnClick:)]) { - [_delegate voiceBtnClick:sender]; - } - -} -//配置角色 -- (void)changeRoleBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - if ([_delegate respondsToSelector:@selector(changeRoleBtnClick:)]) { - [_delegate changeRoleBtnClick:sender]; - } - if ([_delegate isKindOfClass:[UIViewController class]]) { - [self showChangeRoleMenuOnVC:(UIViewController *)_delegate]; - } -} -//日志 -- (void)logBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - if ([_delegate respondsToSelector:@selector(logBtnClick:)]) { - [_delegate logBtnClick:sender]; - } -} -//问题反馈 -- (void)feedBackBtnClick:(UIButton *)sender{ - if (!sender.selected) { - sender.selected = YES; - } - else{ - sender.selected = NO; - } - if ([_delegate respondsToSelector:@selector(feedBackBtnClick:)]) { - [_delegate feedBackBtnClick:sender]; - } - if ([_delegate isKindOfClass:[UIViewController class]]) { - UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"若您在接入过程中有疑问可直接反馈给我们" message:@"邮箱联系地址:trtcfb@qq.com" preferredStyle:UIAlertControllerStyleAlert]; - [alert addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:nil]]; - [((UIViewController *)self.delegate) presentViewController:alert animated:YES completion:nil]; - } -} -//log展示开关 -- (void)enableLog:(BOOL)endable{ - self.logBtn.selected = endable; - if ([_delegate respondsToSelector:@selector(logBtnClick:)]) { - [_delegate logBtnClick:self.logBtn]; - } -} -//弹出配置菜单 --(void)showChangeRoleMenuOnVC:(UIViewController *)vc{ - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"请选择配置分辨率" message:nil preferredStyle:UIAlertControllerStyleAlert]; - [alertController addAction:[UIAlertAction actionWithTitle:@"1280x720 1000-1800kbps 20fps" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[ILiveRoomManager getInstance] changeRole:@"ed1280" succ:^{ - NSLog(@"更换ed1280 succ"); - [self enableLog:YES]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"更换ed1280 fail"); - }]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"960x540 500-800kbps 15fps" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[ILiveRoomManager getInstance] changeRole:@"ed960" succ:^{ - NSLog(@"更换ed960 succ"); - [self enableLog:YES]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"更换ed960 fail"); - }]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"640x480 400-800kbps 15fps" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[ILiveRoomManager getInstance] changeRole:@"ed640" succ:^{ - NSLog(@"更换ed640 succ"); - [self enableLog:YES]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"更换ed640 fail"); - }]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"480x360 300-600kbps 15fps" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[ILiveRoomManager getInstance] changeRole:@"ed480" succ:^{ - NSLog(@"更换ed480 succ"); - [self enableLog:YES]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"更换ed480 fail"); - }]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"320x240 200-400kbps 15fps" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [[ILiveRoomManager getInstance] changeRole:@"ed320" succ:^{ - NSLog(@"更换ed320 succ"); - [self enableLog:YES]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"更换ed320 fail"); - }]; - }]]; - [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]]; - [vc presentViewController:alertController animated:YES completion:nil]; -} -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.h b/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.h deleted file mode 100644 index 1898d10..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// TCLiveVideoLayoutView.h -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import -#import - -@class TCLiveVideoElementView; - -typedef enum { - TCLiveRoomVideoLayoutStyle_1v3, - TCLiveRoomVideoLayoutStyle_4_geizi, -}TCLiveRoomVideoLayoutStyle; - -@protocol TCLiveVideoElementViewDelegate -- (void)tapHandle:(TCLiveVideoElementView *)view; -@end - -@interface TCLiveVideoLayoutView : UIView -//画面布局样式 -@property(nonatomic,assign) TCLiveRoomVideoLayoutStyle layoutStyle; -//显示日志信息 -- (void)showLogView:(NSString *)qualityParams; -//关闭日志信息 -- (void)closeLogView; -//设置美颜 -- (void)setBeautyLevel:(NSInteger)level; -@end - -@interface TCLiveVideoElementView: UIView -//展示userID -@property(nonatomic,strong)UILabel *userIdLabel; -//展示视频分辨率、帧率等信息 -@property(nonatomic,strong)UILabel *videoInfoLable; -@property(nonatomic,weak)TCLiveVideoLayoutView *delegate; -//可拖动开关 -- (void)ennableDraggable:(BOOL)draggable; -@end diff --git a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.m b/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.m deleted file mode 100644 index b13299e..0000000 --- a/src/ios/Trtc/TCLiveRoomVC/TCLiveVideoLayoutView.m +++ /dev/null @@ -1,403 +0,0 @@ -// -// TCLiveVideoLayoutView.m -// TRTC -// -// Created by Tencent on 2018/6/3. -// Copyright © 2018年 Tencent. All rights reserved. -// - -#import "TCLiveVideoLayoutView.h" -#import -#import -#import -#import "TCLiveRequestManager.h" -#import "UIColorEX.h" -#import "TXCVideoPreprocessor.h" -#define LIVE_VIDEO_NUM 4 - -@interface TCLiveVideoLayoutView () -@property(nonatomic,strong)NSMutableArray *liveVideos; -@property(nonatomic,strong)NSMutableArray *liveRnederView; -@property(nonatomic,strong)UITextView *logView; -@property(nonatomic,assign) BOOL isShowLogInfo; -@property(nonatomic,assign) NSDate *startTime; -@property (nonatomic, strong) TXCVideoPreprocessor *preProcessor; -@property (nonatomic, assign) Byte *processorBytes; -@end - -@implementation TCLiveVideoLayoutView - --(instancetype)initWithFrame:(CGRect)frame{ - if (self = [super initWithFrame:frame]) { - self.backgroundColor = [UIColor clearColor]; - self.layoutStyle = TCLiveRoomVideoLayoutStyle_1v3; - [self initialVideoViews]; - [[TILLiveManager getInstance] setAVListener:self]; - [[ILiveRoomManager getInstance] setLocalVideoDelegate:self]; - [[ILiveRoomManager getInstance] setRemoteVideoDelegate:self]; - [[ILiveRoomManager getInstance] setScreenVideoDelegate:self]; - //美颜处理器 - self.preProcessor = [[TXCVideoPreprocessor alloc] init]; - [self.preProcessor setDelegate:self]; - //记录进入时间 - self.startTime = [NSDate date]; - } - return self; -} -//初始化每路视频view -- (void)initialVideoViews{ - _liveVideos = [NSMutableArray array]; - //自定义视窗数组 - NSArray *frames = [self customLayoutFrames]; - for (int i = 0; i < frames.count; i++) { - TCLiveVideoElementView *view = [[TCLiveVideoElementView alloc] initWithFrame:CGRectZero]; - view.delegate = self; - [self addSubview:view]; - [_liveVideos addObject:view]; - } -} --(UITextView *)logView{ - if(!_logView){ - _logView = [[UITextView alloc] initWithFrame:CGRectMake(0, self.frame.size.height/5, self.frame.size.width/3*2, self.frame.size.height/2)]; - _logView.textColor = [UIColor colorWithRGBHex:0xFF4081]; - _logView.font = [UIFont systemFontOfSize:14]; - _logView.backgroundColor = [UIColor clearColor]; - _logView.editable = NO; - } - return _logView; -} - -//自定义布局(开发者可自定义每个视窗的frame来实现,视窗个数即为frames数组个数) -- (NSArray *)customLayoutFrames{ - NSMutableArray *frames = [NSMutableArray array]; - if (TCLiveRoomVideoLayoutStyle_1v3 == _layoutStyle) { - [frames removeAllObjects]; - int smallViewWidth = ((self.frame.size.height - 20 - 150 - 10 *2)/3)*(3.0/4.0); - int smallViewHeight = (self.frame.size.height - 20 - 150 - 10 *2)/3; - CGRect frame1 = self.bounds; - CGRect frame2 = CGRectMake(self.bounds.size.width - 10 - smallViewWidth, 84 , smallViewWidth, smallViewHeight); - CGRect frame3 = CGRectMake(self.bounds.size.width - 10 - smallViewWidth, frame2.origin.y + frame2.size.height + 10, smallViewWidth, smallViewHeight); - CGRect frame4 = CGRectMake(self.bounds.size.width - 10 - smallViewWidth, frame3.origin.y + frame3.size.height + 10, smallViewWidth, smallViewHeight); - - [frames addObject:[NSValue valueWithCGRect:frame1]]; - [frames addObject:[NSValue valueWithCGRect:frame2]]; - [frames addObject:[NSValue valueWithCGRect:frame3]]; - [frames addObject:[NSValue valueWithCGRect:frame4]]; - } - else if (TCLiveRoomVideoLayoutStyle_4_geizi == _layoutStyle) { - [frames removeAllObjects]; - CGRect frame1 = CGRectMake(20, 50, (self.frame.size.width -40)/2, (self.frame.size.height - 100)/2); - CGRect frame2 = CGRectMake(20 + (self.frame.size.width -40)/2 +1, 50, (self.frame.size.width -40)/2, (self.frame.size.height - 100)/2); - CGRect frame3 = CGRectMake(20, 50 + (self.frame.size.height - 100)/2 +1, (self.frame.size.width -40)/2, (self.frame.size.height - 100)/2); - CGRect frame4 = CGRectMake(20 + (self.frame.size.width -40)/2 +1, 50 + (self.frame.size.height - 100)/2 +1,(self.frame.size.width -40)/2, (self.frame.size.height - 100)/2); - [frames addObject:[NSValue valueWithCGRect:frame1]]; - [frames addObject:[NSValue valueWithCGRect:frame2]]; - [frames addObject:[NSValue valueWithCGRect:frame3]]; - [frames addObject:[NSValue valueWithCGRect:frame4]]; - } - return frames; -} - -//添加视频画面 --(void)addLiveRenderView:(ILiveRenderView *)renderView{ - NSArray *frames = [self customLayoutFrames]; - for (int i = 0; i < _liveVideos.count;i++) { - TCLiveVideoElementView *videoView = _liveVideos[i]; - videoView.frame = [frames[i] CGRectValue]; - if (![self getLiveRenderViewOnElementView:videoView]) { - renderView.frame = videoView.bounds; - [videoView insertSubview:renderView atIndex:0]; - break; - } - } -} -//移除视频画面 -- (void)removeLiverRenderVeiw:(ILiveRenderView *)renderView{ - if ([[renderView superview] isKindOfClass:[TCLiveVideoElementView class]]) { - TCLiveVideoElementView *videoView = (TCLiveVideoElementView *)[renderView superview]; - videoView.frame = CGRectZero; - [renderView removeFromSuperview]; - } -} - -//画面切换 -- (void)tapHandle:(TCLiveVideoElementView *)view{ - NSUInteger index = [_liveVideos indexOfObject:view]; - TCLiveVideoElementView *bigView = _liveVideos[0]; - ILiveRenderView *bigRenderView = [self getLiveRenderViewOnElementView:bigView]; - ILiveRenderView *renderView = [self getLiveRenderViewOnElementView:view]; - if (index > 0) { - [UIView animateWithDuration:0.5 animations:^{ - bigView.frame = view.frame; - view.frame = [[self customLayoutFrames][0] CGRectValue]; - bigRenderView.frame = bigView.bounds; - renderView.frame = view.bounds; - [self.liveVideos exchangeObjectAtIndex:0 withObjectAtIndex:index]; - [self exchangeSubviewAtIndex:0 withSubviewAtIndex:index]; - } completion:^(BOOL finished) { - - }]; - - } - -} -//获取指定视窗的渲染view -- (ILiveRenderView *)getLiveRenderViewOnElementView:(TCLiveVideoElementView *)elementView{ - ILiveRenderView *renderView = nil; - for (id view in [elementView subviews]) { - if ([view isKindOfClass:[ILiveRenderView class]]) { - renderView = view; - } - } - return renderView; -} --(void)setBeautyLevel:(NSInteger)level{ - [self.preProcessor setBeautyLevel:level]; -} -#pragma mark - ILiveMemStatusListener -//房间成员状态变化事件 -- (BOOL)onEndpointsUpdateInfo:(QAVUpdateEvent)event updateList:(NSArray *)endpoints{ - if (endpoints.count <= 0) { - return NO; - } - for (QAVEndpoint *endoption in endpoints) { - switch (event) { - case QAV_EVENT_ID_ENDPOINT_HAS_CAMERA_VIDEO: - { - ILiveFrameDispatcher *frameDispatcher = [[ILiveRoomManager getInstance] getFrameDispatcher]; - ILiveRenderView *renderView = [frameDispatcher addRenderAt:CGRectZero forIdentifier:endoption.identifier srcType:QAVVIDEO_SRC_TYPE_CAMERA]; - renderView.isRotate = NO; - renderView.autoRotate = NO; - renderView.isMirror = YES; - renderView.identifier = endoption.identifier; - renderView.diffDirectionRenderMode = ILIVERENDERMODE_SCALEASPECTFILL; - if ([[TCLiveRequestManager getInstance].userID isEqualToString:endoption.identifier]) { - renderView.rotateAngle = ILIVEROTATION_90; - } - [self addLiveRenderView:renderView]; - } - break; - case QAV_EVENT_ID_ENDPOINT_NO_CAMERA_VIDEO: - { - ILiveFrameDispatcher *frameDispatcher = [[ILiveRoomManager getInstance] getFrameDispatcher]; - ILiveRenderView *renderView = [frameDispatcher removeRenderViewFor:endoption.identifier srcType:QAVVIDEO_SRC_TYPE_CAMERA]; - [self removeLiverRenderVeiw:renderView]; - } - break; - - default: - break; - } - } - return YES; -} -/***本地画面帧数据回调***/ -#pragma mark - QAVLocalVideoDelegate -- (void)OnLocalVideoPreview:(QAVVideoFrame *)frameData{ - [self showElementVideoInfoWithVideoFrame:frameData]; -} - -- (void)OnLocalVideoPreProcess:(QAVVideoFrame *)frameData{ - - - [self.preProcessor setOutputSize:CGSizeMake(frameData.frameDesc.width, frameData.frameDesc.height)]; - [self.preProcessor setCropRect:CGRectMake(0, 0,frameData.frameDesc.width, frameData.frameDesc.height)]; - [self.preProcessor processFrame:frameData.data width:frameData.frameDesc.width height:frameData.frameDesc.height orientation:TXE_ROTATION_0 inputFormat:TXE_FRAME_FORMAT_NV12 outputFormat:TXE_FRAME_FORMAT_NV12]; - //将处理完的数据拷贝到原来的地址空间,如果是同步处理,此时会先执行didProcessFrame回调 - if(self.processorBytes){ - memcpy(frameData.data, self.processorBytes, frameData.frameDesc.width * frameData.frameDesc.height * 3 / 2); - } -} - -- (void)OnLocalVideoRawSampleBuf:(CMSampleBufferRef)buf result:(CMSampleBufferRef *)ret{ - -} - -/***远端视频帧数据回调***/ -#pragma mark - QAVRemoteVideoDelegate -- (void)OnVideoPreview:(QAVVideoFrame *)frameData{ - [self showElementVideoInfoWithVideoFrame:frameData]; -} -/***远端屏幕分享帧数据回调***/ -#pragma mark - ILiveScreenVideoDelegate - --(void)onScreenVideoPreview:(QAVVideoFrame *)frameData{ - [self showElementVideoInfoWithVideoFrame:frameData]; -} -/***首帧回调***/ -#pragma mark - ILVLiveAVListener -- (void)onFirstFrameRecved:(int)width height:(int)height identifier:(NSString *)identifier srcType:(avVideoSrcType)srcType;{ - -} -/***美颜相关处理***/ -#pragma mark - TXIVideoPreprocessorDelegate -- (void)didProcessFrame:(Byte *)bytes width:(NSInteger)width height:(NSInteger)height format:(TXEFrameFormat)format timeStamp:(UInt64)timeStamp -{ - self.processorBytes = bytes; -} -#pragma mark - LOG相关 -- (void)showLogView:(NSString *)qualityParams{ - NSString *role = [[[[qualityParams componentsSeparatedByString:@"ControlRole="] lastObject] componentsSeparatedByString:@","] firstObject]; - - self.logView.text = [NSString stringWithFormat:@"发送速率:%ldkbps 丢包率:%.1f%%\n接收速率:%ldkbps 丢包率:%.1f%%\n应用CPU:%.1f%% 系统CPU:%.1f%%\n角色:%@\nSDKAPPID:%d\nSDKVersion:%@",(long)[[ILiveRoomManager getInstance] getQualityData].sendRate,[[ILiveRoomManager getInstance] getQualityData].sendLossRate/100.0,(long)[[ILiveRoomManager getInstance] getQualityData].recvRate,[[ILiveRoomManager getInstance] getQualityData].recvLossRate/100.0,[[ILiveRoomManager getInstance] getQualityData].appCPURate/100.0,[[ILiveRoomManager getInstance] getQualityData].sysCPURate/100.0,role,[TCLiveRequestManager getInstance].sdkAppID,[[ILiveSDK getInstance] getVersion]]; - if(![_logView superview]){ - [self addSubview:_logView]; - } - self.isShowLogInfo = YES; -} - -- (void)showElementVideoInfoWithVideoFrame:(QAVVideoFrame *)frame{ - if(!self.isShowLogInfo){ - return; - } - NSString *userId = frame.identifier; - NSString *fps = @""; - if (userId.length == 0){ - userId = [TCLiveRequestManager getInstance].userID; - } - else{ - NSString *qualityParams = [[[ILiveSDK getInstance] getAVContext].room getQualityTips]; - NSString *decode = [[qualityParams componentsSeparatedByString:@"音频部分:========"] firstObject]; - NSString *itemDecode = [[[[decode componentsSeparatedByString:[NSString stringWithFormat:@"成员:%@",userId]] lastObject] componentsSeparatedByString:@"接收参数"] firstObject]; - fps = [[[[itemDecode componentsSeparatedByString:@"FPS="] lastObject] componentsSeparatedByString:@","] firstObject]; - } - int width = frame.frameDesc.width; - int height = frame.frameDesc.height; - for (int i = 0; i < _liveVideos.count;i++) { - TCLiveVideoElementView *videoView = _liveVideos[i]; - ILiveRenderView *renderView = [self getLiveRenderViewOnElementView:videoView]; - if ([renderView.identifier isEqualToString:userId]) { - if ([userId isEqualToString:[TCLiveRequestManager getInstance].userID]) { - videoView.videoInfoLable.text = [NSString stringWithFormat:@"%dx%d",width,height]; - } - else{ - videoView.videoInfoLable.text = [NSString stringWithFormat:@"%dx%d fps:%d",width,height,[fps intValue]/10]; - } - videoView.userIdLabel.text = [NSString stringWithFormat:@"%@",userId]; - - } - } -} - -- (void)closeLogView{ - [_logView removeFromSuperview]; - _logView = nil; - for (int i = 0; i < _liveVideos.count;i++) { - TCLiveVideoElementView *videoView = _liveVideos[i]; - [videoView.userIdLabel removeFromSuperview]; - videoView.userIdLabel = nil; - [videoView.videoInfoLable removeFromSuperview]; - videoView.videoInfoLable = nil; - } - self.isShowLogInfo = NO; -} -@end - -@interface TCLiveVideoElementView() -@property(nonatomic,strong) UIPanGestureRecognizer *panGesture; -@end - -@implementation TCLiveVideoElementView - --(instancetype)initWithFrame:(CGRect)frame{ - if (self = [super initWithFrame:frame]) { - [self ennableDraggable:YES]; - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestuer:)]; - [self addGestureRecognizer:tap]; - } - return self; -} -- (UILabel *)userIdLabel{ - if (!_userIdLabel) { - _userIdLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 12, self.bounds.size.width, 8)]; - _userIdLabel.textColor = [UIColor colorWithRGBHex:0xFF4081]; - _userIdLabel.textAlignment = NSTextAlignmentLeft; - _userIdLabel.font = [UIFont systemFontOfSize:9]; - [self addSubview:_userIdLabel]; - } - return _userIdLabel; -} --(UILabel *)videoInfoLable{ - if (!_videoInfoLable) { - _videoInfoLable = [[UILabel alloc] initWithFrame:CGRectMake(0, 0 , self.bounds.size.width, 12)]; - _videoInfoLable.textColor = [UIColor colorWithRGBHex:0xFF4081]; - _videoInfoLable.textAlignment = NSTextAlignmentLeft; - _videoInfoLable.font = [UIFont systemFontOfSize:13]; - [self addSubview:_videoInfoLable]; - } - return _videoInfoLable; -} -- (void)layoutSubviews{ - if (self.bounds.size.width == [UIScreen mainScreen].bounds.size.width) { - _videoInfoLable.frame = CGRectMake(0, 84 , self.bounds.size.width, 12); - _userIdLabel.frame = CGRectMake(0, 12 + 84, self.bounds.size.width, 8); - } - else{ - _videoInfoLable.frame = CGRectMake(0, 0 , self.bounds.size.width, 12); - _userIdLabel.frame = CGRectMake(0, 12, self.bounds.size.width, 8); - } -} -//可拖动能力 --(void)ennableDraggable:(BOOL)draggable { - [self setUserInteractionEnabled:YES]; - [self removeConstraints:self.constraints]; - for (NSLayoutConstraint *constraint in self.superview.constraints) { - if ([constraint.firstItem isEqual:self]) { - [self.superview removeConstraint:constraint]; - } - } - [self setTranslatesAutoresizingMaskIntoConstraints:YES]; - if (draggable) { - if (!_panGesture) { - _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; - _panGesture.delegate = self; - [self addGestureRecognizer:_panGesture]; - } - }else{ - if (_panGesture) { - _panGesture = nil; - [self removeGestureRecognizer:_panGesture]; - } - } -} -- (void)tapGestuer:(UITapGestureRecognizer *)gesture{ - if ([_delegate respondsToSelector:@selector(tapHandle:)]) { - [_delegate tapHandle:self]; - } -} -- (void)pan:(UIPanGestureRecognizer *)panGestureRecognizer { - switch (panGestureRecognizer.state) { - case UIGestureRecognizerStateBegan: { - [self dragging:panGestureRecognizer]; - } - break; - case UIGestureRecognizerStateChanged: { - [self dragging:panGestureRecognizer]; - } - break; - default: - break; - } -} - --(void)dragging:(UIPanGestureRecognizer *)panGestureRecognizer { - UIView *view = panGestureRecognizer.view; - CGPoint translation = [panGestureRecognizer translationInView:view.superview]; - CGPoint center = CGPointMake(view.center.x + translation.x, view.center.y + translation.y); - //不能拖过边界 - CGSize size = view.frame.size; - CGSize superSize = view.superview.frame.size; - CGFloat width = size.width; - CGFloat height = size.height; - CGFloat superWidth = superSize.width; - CGFloat superHeight = superSize.height; - center.x = (center.xsuperWidth)?superWidth-width/2:center.x; - center.y = (center.ysuperHeight)?superHeight-height/2:center.y; - - [view setCenter:center]; - [panGestureRecognizer setTranslation:CGPointZero inView:view.superview]; -} -@end - diff --git a/src/ios/TrtcPlugin.h b/src/ios/TrtcPlugin.h index 1da8479..0c246e1 100644 --- a/src/ios/TrtcPlugin.h +++ b/src/ios/TrtcPlugin.h @@ -1,13 +1,15 @@ // // TrtcPlugin.h // -// Created by 布丁丸子酱 on 2018/12/26. // #import @interface TrtcPlugin : CDVPlugin +{ +} -- (void) showCreatePage:(CDVInvokedUrlCommand*)command; +- (void)joinChannel:(CDVInvokedUrlCommand *)command; +- (void)userInfoChange:(CDVInvokedUrlCommand *)command; @end diff --git a/src/ios/TrtcPlugin.m b/src/ios/TrtcPlugin.m index 0bfa416..28a11fd 100644 --- a/src/ios/TrtcPlugin.m +++ b/src/ios/TrtcPlugin.m @@ -1,16 +1,21 @@ // // TrtcPlugin.m // -// Created by 布丁丸子酱 on 2018/12/26. // #import "TrtcPlugin.h" -#import "TCLiveRequestManager.h" -#import -#import "TCLiveJoinRoomViewController.h" -#import -#import "UIToastView.h" -#import + +#import "VideoCallingViewController.h" +// #import "TCLiveRequestManager.h" +// #import +// #import "TCLiveJoinRoomViewController.h" +// #import +// #import "UIToastView.h" +// #import +#import + +#import "Events.h"; +#import "CordovaEventKit.h"; @interface TrtcPlugin() {} @@ -18,32 +23,56 @@ @implementation TrtcPlugin -- (void) showCreatePage:(CDVInvokedUrlCommand*)command { - NSLog(@"showCreatePage"); - [[TCLiveRequestManager getInstance] requestLoginInfo:^(int code) { - if (code == 0) { - dispatch_async(dispatch_get_main_queue(), ^{ - int retCode = [[ILiveSDK getInstance] initSdk:[TCLiveRequestManager getInstance].sdkAppID accountType:[TCLiveRequestManager getInstance].accountType]; - NSLog(@"initSdk success %d",retCode); - if (retCode == 0) { - NSLog(@"userId & sig:"); - NSLog(@"%@", [TCLiveRequestManager getInstance].userID); - NSLog(@"%@", [TCLiveRequestManager getInstance].userSig); - [[ILiveLoginManager getInstance] iLiveLogin:[TCLiveRequestManager getInstance].userID sig:[TCLiveRequestManager getInstance].userSig succ:^{ - NSLog(@"-----> login succ"); - [[UIToastView getInstance] showToastWithMessage:@"登录成功" toastMode:UIToastShowMode_Succ]; - } failed:^(NSString *module, int errId, NSString *errMsg) { - NSLog(@"-----> login fail,%@ %d %@",module, errId, errMsg); - [[UIToastView getInstance] showToastWithMessage:@"登录失败" toastMode:UIToastShowMode_fail]; - }]; - } - }); + + +-(void)joinChannel:(CDVInvokedUrlCommand*)command { + NSDictionary* params = [command.arguments objectAtIndex:0]; + NSLog(@"TRTC - joinChannel::%@",params); + CDVPluginResult* pluginResult = nil; + VideoCallingViewController *vc = [[VideoCallingViewController alloc] + initWithRoomId:[params[@"ROOM_ID"] intValue] + userId:params[@"USER_ID"] + appId:[params[@"SDK_APP_ID"] intValue] + userSig:params[@"USER_SIG"]]; + dispatch_async(dispatch_get_main_queue(), ^{ + if (@available(iOS 13.0, *)){ + vc.modalPresentationStyle = UIModalPresentationFullScreen; } - }]; - TCLiveJoinRoomViewController *vc = [TCLiveJoinRoomViewController new]; -// vc.defaultRoomId = self.defaultRoomId; - UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; - [self.viewController presentViewController:nav animated:YES completion:nil]; + [self.viewController presentViewController:vc animated:YES completion:nil]; + }); +} + + +-(void)userInfoChange:(CDVInvokedUrlCommand*)command { + NSDictionary* params = [command.arguments objectAtIndex:0]; + NSLog(@"TRTC - userInfoChange::%@",params); + [Events fireEvent:@"userinfo.update" extra:params]; +} + + + +#ifdef __CORDOVA_4_0_0 + +- (void)pluginInitialize { + NSLog(@"TRTC - pluginInitialize "); + [self initPlugin]; +} + +#else + +- (CDVPlugin*)initWithWebView:(WKWebView*)theWebView{ + NSLog(@"TRTC - initWithWebView "); + if (self=[super initWithWebView:theWebView]) { + } + [self initPlugin]; + return self; +} + +#endif + +-(void)initPlugin{ + NSLog(@"TRTC - initPlugin "); + [CordovaEventKit init:self]; } @end diff --git a/src/ios/TrtcUserInfo.h b/src/ios/TrtcUserInfo.h new file mode 100644 index 0000000..2bb8371 --- /dev/null +++ b/src/ios/TrtcUserInfo.h @@ -0,0 +1,31 @@ +// +// TrtcUserInfo.h +// shuto-cne +// +// Created by 范大德 on 2022/3/30. +// + +#ifndef TrtcUserInfo_h +#define TrtcUserInfo_h + + +#endif /* TrtcUserInfo_h */ +@interface TrtcUserInfo: NSObject +{} +// 自定义类的初始化方法 + +// 过去类型instancetype 是 id 类型 + +- (instancetype)initWithPersonid:(NSString *)personid; + +- (NSString*) personid; +-(NSString *)displayName; + +-(BOOL)isShareUser; + +-(BOOL)isLocalUser; + +-(void)setLocal:(BOOL) value; +-(void)setDisplayName:(NSString *)value; + +@end diff --git a/src/ios/TrtcUserInfo.m b/src/ios/TrtcUserInfo.m new file mode 100644 index 0000000..5bb1c32 --- /dev/null +++ b/src/ios/TrtcUserInfo.m @@ -0,0 +1,68 @@ +// +// TrtcUserInfo.m +// shuto-cne +// +// Created by 范大德 on 2022/3/21. +// + +#import +#import "TrtcUserInfo.h" +@interface TrtcUserInfo() +{ + NSString* personid; + NSString* displayName; + BOOL local; +} + +@end +@implementation TrtcUserInfo + +- (instancetype)initWithPersonid:(NSString *)userId +{ + personid = userId; + return self; // 返回类本身不能忘 +} + +- (NSString*) personid{ + return personid; +} + + +-(NSString *)displayName{ + return displayName; +} + +-(BOOL)isShareUser{ + return personid != nil && [personid hasPrefix:@"share_"]; +} + +-(BOOL)isLocalUser{ + return local; +} + +-(void)setLocal:(BOOL) value{ + local = value; +} +-(void)setDisplayName:(NSString *)value{ + displayName = value; +} +- (NSUInteger)hash +{ + return [personid hash]; +} + +- (BOOL)isEqual: (id)obj +{ + if( obj == nil){ + return NO; + } + if([obj isKindOfClass: [TrtcUserInfo class]]){ + TrtcUserInfo *user = (TrtcUserInfo*)obj; + return personid == nil ? [user personid] == nil : [personid isEqual: [user personid]]; + } else if([obj isKindOfClass: [NSString class]]){ + return personid == nil ? obj == nil : [personid isEqual: obj]; + } else { + return NO; + } +} +@end diff --git a/src/ios/UIView+Toast.h b/src/ios/UIView+Toast.h new file mode 100644 index 0000000..e2b258b --- /dev/null +++ b/src/ios/UIView+Toast.h @@ -0,0 +1,446 @@ +// +// UIView+Toast.h +// Toast +// +// Copyright (c) 2011-2017 Charles Scalesse. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#import + +extern const NSString * CSToastPositionTop; +extern const NSString * CSToastPositionCenter; +extern const NSString * CSToastPositionBottom; + +@class CSToastStyle; + +/** + Toast is an Objective-C category that adds toast notifications to the UIView + object class. It is intended to be simple, lightweight, and easy to use. Most + toast notifications can be triggered with a single line of code. + + The `makeToast:` methods create a new view and then display it as toast. + + The `showToast:` methods display any view as toast. + + */ +@interface UIView (Toast) + +/** + Creates and presents a new toast view with a message and displays it with the + default duration and position. Styled using the shared style. + + @param message The message to be displayed + */ +- (void)makeToast:(NSString *)message; + +/** + Creates and presents a new toast view with a message. Duration and position + can be set explicitly. Styled using the shared style. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + */ +- (void)makeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position; + +/** + Creates and presents a new toast view with a message. Duration, position, and + style can be set explicitly. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param style The style. The shared style will be used when nil + */ +- (void)makeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position + style:(CSToastStyle *)style; + +/** + Creates and presents a new toast view with a message, title, and image. Duration, + position, and style can be set explicitly. The completion block executes when the + toast view completes. `didTap` will be `YES` if the toast view was dismissed from + a tap. + + @param message The message to be displayed + @param duration The toast duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param title The title + @param image The image + @param style The style. The shared style will be used when nil + @param completion The completion block, executed after the toast view disappears. + didTap will be `YES` if the toast view was dismissed from a tap. + */ +- (void)makeToast:(NSString *)message + duration:(NSTimeInterval)duration + position:(id)position + title:(NSString *)title + image:(UIImage *)image + style:(CSToastStyle *)style + completion:(void(^)(BOOL didTap))completion; + +/** + Creates a new toast view with any combination of message, title, and image. + The look and feel is configured via the style. Unlike the `makeToast:` methods, + this method does not present the toast view automatically. One of the showToast: + methods must be used to present the resulting view. + + @warning if message, title, and image are all nil, this method will return nil. + + @param message The message to be displayed + @param title The title + @param image The image + @param style The style. The shared style will be used when nil + @return The newly created toast view + */ +- (UIView *)toastViewForMessage:(NSString *)message + title:(NSString *)title + image:(UIImage *)image + style:(CSToastStyle *)style; + +/** + Hides the active toast. If there are multiple toasts active in a view, this method + hides the oldest toast (the first of the toasts to have been presented). + + @see `hideAllToasts` to remove all active toasts from a view. + + @warning This method has no effect on activity toasts. Use `hideToastActivity` to + hide activity toasts. + */ +- (void)hideToast; + +/** + Hides an active toast. + + @param toast The active toast view to dismiss. Any toast that is currently being displayed + on the screen is considered active. + + @warning this does not clear a toast view that is currently waiting in the queue. + */ +- (void)hideToast:(UIView *)toast; + +/** + Hides all active toast views and clears the queue. + */ +- (void)hideAllToasts; + +/** + Hides all active toast views, with options to hide activity and clear the queue. + + @param includeActivity If `true`, toast activity will also be hidden. Default is `false`. + @param clearQueue If `true`, removes all toast views from the queue. Default is `true`. + */ +- (void)hideAllToasts:(BOOL)includeActivity clearQueue:(BOOL)clearQueue; + +/** + Removes all toast views from the queue. This has no effect on toast views that are + active. Use `hideAllToasts` to hide the active toasts views and clear the queue. + */ +- (void)clearToastQueue; + +/** + Creates and displays a new toast activity indicator view at a specified position. + + @warning Only one toast activity indicator view can be presented per superview. Subsequent + calls to `makeToastActivity:` will be ignored until hideToastActivity is called. + + @warning `makeToastActivity:` works independently of the showToast: methods. Toast activity + views can be presented and dismissed while toast views are being displayed. `makeToastActivity:` + has no effect on the queueing behavior of the showToast: methods. + + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + */ +- (void)makeToastActivity:(id)position; + +/** + Dismisses the active toast activity indicator view. + */ +- (void)hideToastActivity; + +/** + Displays any view as toast using the default duration and position. + + @param toast The view to be displayed as toast + */ +- (void)showToast:(UIView *)toast; + +/** + Displays any view as toast at a provided position and duration. The completion block + executes when the toast view completes. `didTap` will be `YES` if the toast view was + dismissed from a tap. + + @param toast The view to be displayed as toast + @param duration The notification duration + @param position The toast's center point. Can be one of the predefined CSToastPosition + constants or a `CGPoint` wrapped in an `NSValue` object. + @param completion The completion block, executed after the toast view disappears. + didTap will be `YES` if the toast view was dismissed from a tap. + */ +- (void)showToast:(UIView *)toast + duration:(NSTimeInterval)duration + position:(id)position + completion:(void(^)(BOOL didTap))completion; + +@end + +/** + `CSToastStyle` instances define the look and feel for toast views created via the + `makeToast:` methods as well for toast views created directly with + `toastViewForMessage:title:image:style:`. + + @warning `CSToastStyle` offers relatively simple styling options for the default + toast view. If you require a toast view with more complex UI, it probably makes more + sense to create your own custom UIView subclass and present it with the `showToast:` + methods. + */ +@interface CSToastStyle : NSObject + +/** + The background color. Default is `[UIColor blackColor]` at 80% opacity. + */ +@property (strong, nonatomic) UIColor *backgroundColor; + +/** + The title color. Default is `[UIColor whiteColor]`. + */ +@property (strong, nonatomic) UIColor *titleColor; + +/** + The message color. Default is `[UIColor whiteColor]`. + */ +@property (strong, nonatomic) UIColor *messageColor; + +/** + A percentage value from 0.0 to 1.0, representing the maximum width of the toast + view relative to it's superview. Default is 0.8 (80% of the superview's width). + */ +@property (assign, nonatomic) CGFloat maxWidthPercentage; + +/** + A percentage value from 0.0 to 1.0, representing the maximum height of the toast + view relative to it's superview. Default is 0.8 (80% of the superview's height). + */ +@property (assign, nonatomic) CGFloat maxHeightPercentage; + +/** + The spacing from the horizontal edge of the toast view to the content. When an image + is present, this is also used as the padding between the image and the text. + Default is 10.0. + */ +@property (assign, nonatomic) CGFloat horizontalPadding; + +/** + The spacing from the vertical edge of the toast view to the content. When a title + is present, this is also used as the padding between the title and the message. + Default is 10.0. + */ +@property (assign, nonatomic) CGFloat verticalPadding; + +/** + The corner radius. Default is 10.0. + */ +@property (assign, nonatomic) CGFloat cornerRadius; + +/** + The title font. Default is `[UIFont boldSystemFontOfSize:16.0]`. + */ +@property (strong, nonatomic) UIFont *titleFont; + +/** + The message font. Default is `[UIFont systemFontOfSize:16.0]`. + */ +@property (strong, nonatomic) UIFont *messageFont; + +/** + The title text alignment. Default is `NSTextAlignmentLeft`. + */ +@property (assign, nonatomic) NSTextAlignment titleAlignment; + +/** + The message text alignment. Default is `NSTextAlignmentLeft`. + */ +@property (assign, nonatomic) NSTextAlignment messageAlignment; + +/** + The maximum number of lines for the title. The default is 0 (no limit). + */ +@property (assign, nonatomic) NSInteger titleNumberOfLines; + +/** + The maximum number of lines for the message. The default is 0 (no limit). + */ +@property (assign, nonatomic) NSInteger messageNumberOfLines; + +/** + Enable or disable a shadow on the toast view. Default is `NO`. + */ +@property (assign, nonatomic) BOOL displayShadow; + +/** + The shadow color. Default is `[UIColor blackColor]`. + */ +@property (strong, nonatomic) UIColor *shadowColor; + +/** + A value from 0.0 to 1.0, representing the opacity of the shadow. + Default is 0.8 (80% opacity). + */ +@property (assign, nonatomic) CGFloat shadowOpacity; + +/** + The shadow radius. Default is 6.0. + */ +@property (assign, nonatomic) CGFloat shadowRadius; + +/** + The shadow offset. The default is `CGSizeMake(4.0, 4.0)`. + */ +@property (assign, nonatomic) CGSize shadowOffset; + +/** + The image size. The default is `CGSizeMake(80.0, 80.0)`. + */ +@property (assign, nonatomic) CGSize imageSize; + +/** + The size of the toast activity view when `makeToastActivity:` is called. + Default is `CGSizeMake(100.0, 100.0)`. + */ +@property (assign, nonatomic) CGSize activitySize; + +/** + The fade in/out animation duration. Default is 0.2. + */ +@property (assign, nonatomic) NSTimeInterval fadeDuration; + +/** + Creates a new instance of `CSToastStyle` with all the default values set. + */ +- (instancetype)initWithDefaultStyle NS_DESIGNATED_INITIALIZER; + +/** + @warning Only the designated initializer should be used to create + an instance of `CSToastStyle`. + */ +- (instancetype)init NS_UNAVAILABLE; + +@end + +/** + `CSToastManager` provides general configuration options for all toast + notifications. Backed by a singleton instance. + */ +@interface CSToastManager : NSObject + +/** + Sets the shared style on the singleton. The shared style is used whenever + a `makeToast:` method (or `toastViewForMessage:title:image:style:`) is called + with with a nil style. By default, this is set to `CSToastStyle`'s default + style. + + @param sharedStyle the shared style + */ ++ (void)setSharedStyle:(CSToastStyle *)sharedStyle; + +/** + Gets the shared style from the singlton. By default, this is + `CSToastStyle`'s default style. + + @return the shared style + */ ++ (CSToastStyle *)sharedStyle; + +/** + Enables or disables tap to dismiss on toast views. Default is `YES`. + + @param tapToDismissEnabled YES or NO + */ ++ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled; + +/** + Returns `YES` if tap to dismiss is enabled, otherwise `NO`. + Default is `YES`. + + @return BOOL YES or NO + */ ++ (BOOL)isTapToDismissEnabled; + +/** + Enables or disables queueing behavior for toast views. When `YES`, + toast views will appear one after the other. When `NO`, multiple Toast + views will appear at the same time (potentially overlapping depending + on their positions). This has no effect on the toast activity view, + which operates independently of normal toast views. Default is `NO`. + + @param queueEnabled YES or NO + */ ++ (void)setQueueEnabled:(BOOL)queueEnabled; + +/** + Returns `YES` if the queue is enabled, otherwise `NO`. + Default is `NO`. + + @return BOOL + */ ++ (BOOL)isQueueEnabled; + +/** + Sets the default duration. Used for the `makeToast:` and + `showToast:` methods that don't require an explicit duration. + Default is 3.0. + + @param duration The toast duration + */ ++ (void)setDefaultDuration:(NSTimeInterval)duration; + +/** + Returns the default duration. Default is 3.0. + + @return duration The toast duration +*/ ++ (NSTimeInterval)defaultDuration; + +/** + Sets the default position. Used for the `makeToast:` and + `showToast:` methods that don't require an explicit position. + Default is `CSToastPositionBottom`. + + @param position The default center point. Can be one of the predefined + CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. + */ ++ (void)setDefaultPosition:(id)position; + +/** + Returns the default toast position. Default is `CSToastPositionBottom`. + + @return position The default center point. Will be one of the predefined + CSToastPosition constants or a `CGPoint` wrapped in an `NSValue` object. + */ ++ (id)defaultPosition; + +@end diff --git a/src/ios/UIView+Toast.m b/src/ios/UIView+Toast.m new file mode 100644 index 0000000..4e5131a --- /dev/null +++ b/src/ios/UIView+Toast.m @@ -0,0 +1,586 @@ +// +// UIView+Toast.m +// Toast +// +// Copyright (c) 2011-2017 Charles Scalesse. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#import "UIView+Toast.h" +#import +#import + +// Positions +NSString * CSToastPositionTop = @"CSToastPositionTop"; +NSString * CSToastPositionCenter = @"CSToastPositionCenter"; +NSString * CSToastPositionBottom = @"CSToastPositionBottom"; + +// Keys for values associated with toast views +static const NSString * CSToastTimerKey = @"CSToastTimerKey"; +static const NSString * CSToastDurationKey = @"CSToastDurationKey"; +static const NSString * CSToastPositionKey = @"CSToastPositionKey"; +static const NSString * CSToastCompletionKey = @"CSToastCompletionKey"; + +// Keys for values associated with self +static const NSString * CSToastActiveKey = @"CSToastActiveKey"; +static const NSString * CSToastActivityViewKey = @"CSToastActivityViewKey"; +static const NSString * CSToastQueueKey = @"CSToastQueueKey"; + +@interface UIView (ToastPrivate) + +/** + These private methods are being prefixed with "cs_" to reduce the likelihood of non-obvious + naming conflicts with other UIView methods. + + @discussion Should the public API also use the cs_ prefix? Technically it should, but it + results in code that is less legible. The current public method names seem unlikely to cause + conflicts so I think we should favor the cleaner API for now. + */ +- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position; +- (void)cs_hideToast:(UIView *)toast; +- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap; +- (void)cs_toastTimerDidFinish:(NSTimer *)timer; +- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer; +- (CGPoint)cs_centerPointForPosition:(id)position withToast:(UIView *)toast; +- (NSMutableArray *)cs_toastQueue; + +@end + +@implementation UIView (Toast) + +#pragma mark - Make Toast Methods + +- (void)makeToast:(NSString *)message { + [self makeToast:message duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] style:nil]; +} + +- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position { + [self makeToast:message duration:duration position:position style:nil]; +} + +- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position style:(CSToastStyle *)style { + UIView *toast = [self toastViewForMessage:message title:nil image:nil style:style]; + [self showToast:toast duration:duration position:position completion:nil]; +} + +- (void)makeToast:(NSString *)message duration:(NSTimeInterval)duration position:(id)position title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style completion:(void(^)(BOOL didTap))completion { + UIView *toast = [self toastViewForMessage:message title:title image:image style:style]; + [self showToast:toast duration:duration position:position completion:completion]; +} + +#pragma mark - Show Toast Methods + +- (void)showToast:(UIView *)toast { + [self showToast:toast duration:[CSToastManager defaultDuration] position:[CSToastManager defaultPosition] completion:nil]; +} + +- (void)showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position completion:(void(^)(BOOL didTap))completion { + // sanity + if (toast == nil) return; + + // store the completion block on the toast view + objc_setAssociatedObject(toast, &CSToastCompletionKey, completion, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + if ([CSToastManager isQueueEnabled] && [self.cs_activeToasts count] > 0) { + // we're about to queue this toast view so we need to store the duration and position as well + objc_setAssociatedObject(toast, &CSToastDurationKey, @(duration), OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(toast, &CSToastPositionKey, position, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + // enqueue + [self.cs_toastQueue addObject:toast]; + } else { + // present + [self cs_showToast:toast duration:duration position:position]; + } +} + +#pragma mark - Hide Toast Methods + +- (void)hideToast { + [self hideToast:[[self cs_activeToasts] firstObject]]; +} + +- (void)hideToast:(UIView *)toast { + // sanity + if (!toast || ![[self cs_activeToasts] containsObject:toast]) return; + + [self cs_hideToast:toast]; +} + +- (void)hideAllToasts { + [self hideAllToasts:NO clearQueue:YES]; +} + +- (void)hideAllToasts:(BOOL)includeActivity clearQueue:(BOOL)clearQueue { + if (clearQueue) { + [self clearToastQueue]; + } + + for (UIView *toast in [self cs_activeToasts]) { + [self hideToast:toast]; + } + + if (includeActivity) { + [self hideToastActivity]; + } +} + +- (void)clearToastQueue { + [[self cs_toastQueue] removeAllObjects]; +} + +#pragma mark - Private Show/Hide Methods + +- (void)cs_showToast:(UIView *)toast duration:(NSTimeInterval)duration position:(id)position { + toast.center = [self cs_centerPointForPosition:position withToast:toast]; + toast.alpha = 0.0; + + if ([CSToastManager isTapToDismissEnabled]) { + UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(cs_handleToastTapped:)]; + [toast addGestureRecognizer:recognizer]; + toast.userInteractionEnabled = YES; + toast.exclusiveTouch = YES; + } + + [[self cs_activeToasts] addObject:toast]; + + [self addSubview:toast]; + + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionAllowUserInteraction) + animations:^{ + toast.alpha = 1.0; + } completion:^(BOOL finished) { + NSTimer *timer = [NSTimer timerWithTimeInterval:duration target:self selector:@selector(cs_toastTimerDidFinish:) userInfo:toast repeats:NO]; + [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; + objc_setAssociatedObject(toast, &CSToastTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }]; +} + +- (void)cs_hideToast:(UIView *)toast { + [self cs_hideToast:toast fromTap:NO]; +} + +- (void)cs_hideToast:(UIView *)toast fromTap:(BOOL)fromTap { + NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey); + [timer invalidate]; + + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + toast.alpha = 0.0; + } completion:^(BOOL finished) { + [toast removeFromSuperview]; + + // remove + [[self cs_activeToasts] removeObject:toast]; + + // execute the completion block, if necessary + void (^completion)(BOOL didTap) = objc_getAssociatedObject(toast, &CSToastCompletionKey); + if (completion) { + completion(fromTap); + } + + if ([self.cs_toastQueue count] > 0) { + // dequeue + UIView *nextToast = [[self cs_toastQueue] firstObject]; + [[self cs_toastQueue] removeObjectAtIndex:0]; + + // present the next toast + NSTimeInterval duration = [objc_getAssociatedObject(nextToast, &CSToastDurationKey) doubleValue]; + id position = objc_getAssociatedObject(nextToast, &CSToastPositionKey); + [self cs_showToast:nextToast duration:duration position:position]; + } + }]; +} + +#pragma mark - View Construction + +- (UIView *)toastViewForMessage:(NSString *)message title:(NSString *)title image:(UIImage *)image style:(CSToastStyle *)style { + // sanity + if (message == nil && title == nil && image == nil) return nil; + + // default to the shared style + if (style == nil) { + style = [CSToastManager sharedStyle]; + } + + // dynamically build a toast view with any combination of message, title, & image + UILabel *messageLabel = nil; + UILabel *titleLabel = nil; + UIImageView *imageView = nil; + + UIView *wrapperView = [[UIView alloc] init]; + wrapperView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + wrapperView.layer.cornerRadius = style.cornerRadius; + + if (style.displayShadow) { + wrapperView.layer.shadowColor = style.shadowColor.CGColor; + wrapperView.layer.shadowOpacity = style.shadowOpacity; + wrapperView.layer.shadowRadius = style.shadowRadius; + wrapperView.layer.shadowOffset = style.shadowOffset; + } + + wrapperView.backgroundColor = style.backgroundColor; + + if(image != nil) { + imageView = [[UIImageView alloc] initWithImage:image]; + imageView.contentMode = UIViewContentModeScaleAspectFit; + imageView.frame = CGRectMake(style.horizontalPadding, style.verticalPadding, style.imageSize.width, style.imageSize.height); + } + + CGRect imageRect = CGRectZero; + + if(imageView != nil) { + imageRect.origin.x = style.horizontalPadding; + imageRect.origin.y = style.verticalPadding; + imageRect.size.width = imageView.bounds.size.width; + imageRect.size.height = imageView.bounds.size.height; + } + + if (title != nil) { + titleLabel = [[UILabel alloc] init]; + titleLabel.numberOfLines = style.titleNumberOfLines; + titleLabel.font = style.titleFont; + titleLabel.textAlignment = style.titleAlignment; + titleLabel.lineBreakMode = NSLineBreakByTruncatingTail; + titleLabel.textColor = style.titleColor; + titleLabel.backgroundColor = [UIColor clearColor]; + titleLabel.alpha = 1.0; + titleLabel.text = title; + + // size the title label according to the length of the text + CGSize maxSizeTitle = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); + CGSize expectedSizeTitle = [titleLabel sizeThatFits:maxSizeTitle]; + // UILabel can return a size larger than the max size when the number of lines is 1 + expectedSizeTitle = CGSizeMake(MIN(maxSizeTitle.width, expectedSizeTitle.width), MIN(maxSizeTitle.height, expectedSizeTitle.height)); + titleLabel.frame = CGRectMake(0.0, 0.0, expectedSizeTitle.width, expectedSizeTitle.height); + } + + if (message != nil) { + messageLabel = [[UILabel alloc] init]; + messageLabel.numberOfLines = style.messageNumberOfLines; + messageLabel.font = style.messageFont; + messageLabel.textAlignment = style.messageAlignment; + messageLabel.lineBreakMode = NSLineBreakByTruncatingTail; + messageLabel.textColor = style.messageColor; + messageLabel.backgroundColor = [UIColor clearColor]; + messageLabel.alpha = 1.0; + messageLabel.text = message; + + CGSize maxSizeMessage = CGSizeMake((self.bounds.size.width * style.maxWidthPercentage) - imageRect.size.width, self.bounds.size.height * style.maxHeightPercentage); + CGSize expectedSizeMessage = [messageLabel sizeThatFits:maxSizeMessage]; + // UILabel can return a size larger than the max size when the number of lines is 1 + expectedSizeMessage = CGSizeMake(MIN(maxSizeMessage.width, expectedSizeMessage.width), MIN(maxSizeMessage.height, expectedSizeMessage.height)); + messageLabel.frame = CGRectMake(0.0, 0.0, expectedSizeMessage.width, expectedSizeMessage.height); + } + + CGRect titleRect = CGRectZero; + + if(titleLabel != nil) { + titleRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; + titleRect.origin.y = style.verticalPadding; + titleRect.size.width = titleLabel.bounds.size.width; + titleRect.size.height = titleLabel.bounds.size.height; + } + + CGRect messageRect = CGRectZero; + + if(messageLabel != nil) { + messageRect.origin.x = imageRect.origin.x + imageRect.size.width + style.horizontalPadding; + messageRect.origin.y = titleRect.origin.y + titleRect.size.height + style.verticalPadding; + messageRect.size.width = messageLabel.bounds.size.width; + messageRect.size.height = messageLabel.bounds.size.height; + } + + CGFloat longerWidth = MAX(titleRect.size.width, messageRect.size.width); + CGFloat longerX = MAX(titleRect.origin.x, messageRect.origin.x); + + // Wrapper width uses the longerWidth or the image width, whatever is larger. Same logic applies to the wrapper height. + CGFloat wrapperWidth = MAX((imageRect.size.width + (style.horizontalPadding * 2.0)), (longerX + longerWidth + style.horizontalPadding)); + CGFloat wrapperHeight = MAX((messageRect.origin.y + messageRect.size.height + style.verticalPadding), (imageRect.size.height + (style.verticalPadding * 2.0))); + + wrapperView.frame = CGRectMake(0.0, 0.0, wrapperWidth, wrapperHeight); + + if(titleLabel != nil) { + titleLabel.frame = titleRect; + [wrapperView addSubview:titleLabel]; + } + + if(messageLabel != nil) { + messageLabel.frame = messageRect; + [wrapperView addSubview:messageLabel]; + } + + if(imageView != nil) { + [wrapperView addSubview:imageView]; + } + + return wrapperView; +} + +#pragma mark - Storage + +- (NSMutableArray *)cs_activeToasts { + NSMutableArray *cs_activeToasts = objc_getAssociatedObject(self, &CSToastActiveKey); + if (cs_activeToasts == nil) { + cs_activeToasts = [[NSMutableArray alloc] init]; + objc_setAssociatedObject(self, &CSToastActiveKey, cs_activeToasts, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return cs_activeToasts; +} + +- (NSMutableArray *)cs_toastQueue { + NSMutableArray *cs_toastQueue = objc_getAssociatedObject(self, &CSToastQueueKey); + if (cs_toastQueue == nil) { + cs_toastQueue = [[NSMutableArray alloc] init]; + objc_setAssociatedObject(self, &CSToastQueueKey, cs_toastQueue, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return cs_toastQueue; +} + +#pragma mark - Events + +- (void)cs_toastTimerDidFinish:(NSTimer *)timer { + [self cs_hideToast:(UIView *)timer.userInfo]; +} + +- (void)cs_handleToastTapped:(UITapGestureRecognizer *)recognizer { + UIView *toast = recognizer.view; + NSTimer *timer = (NSTimer *)objc_getAssociatedObject(toast, &CSToastTimerKey); + [timer invalidate]; + + [self cs_hideToast:toast fromTap:YES]; +} + +#pragma mark - Activity Methods + +- (void)makeToastActivity:(id)position { + // sanity + UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); + if (existingActivityView != nil) return; + + CSToastStyle *style = [CSToastManager sharedStyle]; + + UIView *activityView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, style.activitySize.width, style.activitySize.height)]; + activityView.center = [self cs_centerPointForPosition:position withToast:activityView]; + activityView.backgroundColor = style.backgroundColor; + activityView.alpha = 0.0; + activityView.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin); + activityView.layer.cornerRadius = style.cornerRadius; + + if (style.displayShadow) { + activityView.layer.shadowColor = style.shadowColor.CGColor; + activityView.layer.shadowOpacity = style.shadowOpacity; + activityView.layer.shadowRadius = style.shadowRadius; + activityView.layer.shadowOffset = style.shadowOffset; + } + + UIActivityIndicatorView *activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; + activityIndicatorView.center = CGPointMake(activityView.bounds.size.width / 2, activityView.bounds.size.height / 2); + [activityView addSubview:activityIndicatorView]; + [activityIndicatorView startAnimating]; + + // associate the activity view with self + objc_setAssociatedObject (self, &CSToastActivityViewKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + + [self addSubview:activityView]; + + [UIView animateWithDuration:style.fadeDuration + delay:0.0 + options:UIViewAnimationOptionCurveEaseOut + animations:^{ + activityView.alpha = 1.0; + } completion:nil]; +} + +- (void)hideToastActivity { + UIView *existingActivityView = (UIView *)objc_getAssociatedObject(self, &CSToastActivityViewKey); + if (existingActivityView != nil) { + [UIView animateWithDuration:[[CSToastManager sharedStyle] fadeDuration] + delay:0.0 + options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState) + animations:^{ + existingActivityView.alpha = 0.0; + } completion:^(BOOL finished) { + [existingActivityView removeFromSuperview]; + objc_setAssociatedObject (self, &CSToastActivityViewKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + }]; + } +} + +#pragma mark - Helpers + +- (CGPoint)cs_centerPointForPosition:(id)point withToast:(UIView *)toast { + CSToastStyle *style = [CSToastManager sharedStyle]; + + UIEdgeInsets safeInsets = UIEdgeInsetsZero; + if (@available(iOS 11.0, *)) { + safeInsets = self.safeAreaInsets; + } + + CGFloat topPadding = style.verticalPadding + safeInsets.top; + CGFloat bottomPadding = style.verticalPadding + safeInsets.bottom; + + if([point isKindOfClass:[NSString class]]) { + if([point caseInsensitiveCompare:CSToastPositionTop] == NSOrderedSame) { + return CGPointMake(self.bounds.size.width / 2.0, (toast.frame.size.height / 2.0) + topPadding); + } else if([point caseInsensitiveCompare:CSToastPositionCenter] == NSOrderedSame) { + return CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0); + } + } else if ([point isKindOfClass:[NSValue class]]) { + return [point CGPointValue]; + } + + // default to bottom + return CGPointMake(self.bounds.size.width / 2.0, (self.bounds.size.height - (toast.frame.size.height / 2.0)) - bottomPadding); +} + +@end + +@implementation CSToastStyle + +#pragma mark - Constructors + +- (instancetype)initWithDefaultStyle { + self = [super init]; + if (self) { + self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.8]; + self.titleColor = [UIColor whiteColor]; + self.messageColor = [UIColor whiteColor]; + self.maxWidthPercentage = 0.8; + self.maxHeightPercentage = 0.8; + self.horizontalPadding = 10.0; + self.verticalPadding = 10.0; + self.cornerRadius = 10.0; + self.titleFont = [UIFont boldSystemFontOfSize:16.0]; + self.messageFont = [UIFont systemFontOfSize:16.0]; + self.titleAlignment = NSTextAlignmentLeft; + self.messageAlignment = NSTextAlignmentLeft; + self.titleNumberOfLines = 0; + self.messageNumberOfLines = 0; + self.displayShadow = NO; + self.shadowOpacity = 0.8; + self.shadowRadius = 6.0; + self.shadowOffset = CGSizeMake(4.0, 4.0); + self.imageSize = CGSizeMake(80.0, 80.0); + self.activitySize = CGSizeMake(100.0, 100.0); + self.fadeDuration = 0.2; + } + return self; +} + +- (void)setMaxWidthPercentage:(CGFloat)maxWidthPercentage { + _maxWidthPercentage = MAX(MIN(maxWidthPercentage, 1.0), 0.0); +} + +- (void)setMaxHeightPercentage:(CGFloat)maxHeightPercentage { + _maxHeightPercentage = MAX(MIN(maxHeightPercentage, 1.0), 0.0); +} + +- (instancetype)init NS_UNAVAILABLE { + return nil; +} + +@end + +@interface CSToastManager () + +@property (strong, nonatomic) CSToastStyle *sharedStyle; +@property (assign, nonatomic, getter=isTapToDismissEnabled) BOOL tapToDismissEnabled; +@property (assign, nonatomic, getter=isQueueEnabled) BOOL queueEnabled; +@property (assign, nonatomic) NSTimeInterval defaultDuration; +@property (strong, nonatomic) id defaultPosition; + +@end + +@implementation CSToastManager + +#pragma mark - Constructors + ++ (instancetype)sharedManager { + static CSToastManager *_sharedManager = nil; + static dispatch_once_t oncePredicate; + dispatch_once(&oncePredicate, ^{ + _sharedManager = [[self alloc] init]; + }); + + return _sharedManager; +} + +- (instancetype)init { + self = [super init]; + if (self) { + self.sharedStyle = [[CSToastStyle alloc] initWithDefaultStyle]; + self.tapToDismissEnabled = YES; + self.queueEnabled = NO; + self.defaultDuration = 3.0; + self.defaultPosition = CSToastPositionBottom; + } + return self; +} + +#pragma mark - Singleton Methods + ++ (void)setSharedStyle:(CSToastStyle *)sharedStyle { + [[self sharedManager] setSharedStyle:sharedStyle]; +} + ++ (CSToastStyle *)sharedStyle { + return [[self sharedManager] sharedStyle]; +} + ++ (void)setTapToDismissEnabled:(BOOL)tapToDismissEnabled { + [[self sharedManager] setTapToDismissEnabled:tapToDismissEnabled]; +} + ++ (BOOL)isTapToDismissEnabled { + return [[self sharedManager] isTapToDismissEnabled]; +} + ++ (void)setQueueEnabled:(BOOL)queueEnabled { + [[self sharedManager] setQueueEnabled:queueEnabled]; +} + ++ (BOOL)isQueueEnabled { + return [[self sharedManager] isQueueEnabled]; +} + ++ (void)setDefaultDuration:(NSTimeInterval)duration { + [[self sharedManager] setDefaultDuration:duration]; +} + ++ (NSTimeInterval)defaultDuration { + return [[self sharedManager] defaultDuration]; +} + ++ (void)setDefaultPosition:(id)position { + if ([position isKindOfClass:[NSString class]] || [position isKindOfClass:[NSValue class]]) { + [[self sharedManager] setDefaultPosition:position]; + } +} + ++ (id)defaultPosition { + return [[self sharedManager] defaultPosition]; +} + +@end diff --git a/src/ios/UserUpdateListener.h b/src/ios/UserUpdateListener.h new file mode 100644 index 0000000..29e08cb --- /dev/null +++ b/src/ios/UserUpdateListener.h @@ -0,0 +1,18 @@ +// +// UserUpdateListener.h +// shuto-cne +// +// Created by 范大德 on 2022/3/30. +// + +#ifndef UserUpdateListener_h +#define UserUpdateListener_h + + +#endif /* UserUpdateListener_h */ + +#import "Listener.h" + +@interface UserUpdateListener:Listener +{} +@end diff --git a/src/ios/UserUpdateListener.m b/src/ios/UserUpdateListener.m new file mode 100644 index 0000000..ca1afd7 --- /dev/null +++ b/src/ios/UserUpdateListener.m @@ -0,0 +1,24 @@ +// +// Listener.m +// shuto-cne +// +// Created by 范大德 on 2022/3/29. +// + +#import "UserUpdateListener.h" +#import "VideoCallingViewController.h" +@interface UserUpdateListener() +{} +@end +@implementation UserUpdateListener + +- (instancetype)init { + return self; +} + + +-(void)on: (NSDictionary*)extra{ + [[VideoCallingViewController viewController]updateUser:extra]; +} + +@end diff --git a/src/ios/VideoCallingViewController.h b/src/ios/VideoCallingViewController.h new file mode 100755 index 0000000..be85877 --- /dev/null +++ b/src/ios/VideoCallingViewController.h @@ -0,0 +1,23 @@ +// +// VideoCallingViewController.h +// TRTC-API-Example-OC +// +// Created by bluedang on 2021/4/12. +// + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +//MARK: 视频通话示例 - 通话界面 +@interface VideoCallingViewController : UIViewController +- (instancetype)initWithRoomId:(UInt32)roomId userId:(NSString *)userId appId:(UInt32 *)appId userSig:(NSString *) userSig; +- (NSMutableOrderedSet *)remoteUidSet; ++(VideoCallingViewController*)viewController; +- (void)refreshRemoteVideoViews; +- (void) updateUser:(NSDictionary*)extra; +@end + +NS_ASSUME_NONNULL_END diff --git a/src/ios/VideoCallingViewController.m b/src/ios/VideoCallingViewController.m new file mode 100755 index 0000000..d4541af --- /dev/null +++ b/src/ios/VideoCallingViewController.m @@ -0,0 +1,402 @@ +// +// VideoCallingViewController.m +// TRTC-API-Example-OC +// +// Created by bluedang on 2021/4/12. +// + +/* +实时视频通话功能 + TRTC APP 实时视频通话功能 + 本文件展示如何集成实时视频通话功能 + 1、切换摄像头 API:[[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera]; + 2、打开关闭摄像头 API: [self.trtcCloud startLocalPreview:_isFrontCamera view:_localVideoView]; + [self.trtcCloud stopLocalPreview]; + 3、切换听筒与扬声器 API:[[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece]; + [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone]; + 4、静音当前设备,其他人将无法听到该设备的声音 API: [_trtcCloud muteLocalAudio:YES]; + 参考文档:https://cloud.tencent.com/document/product/647/42044 + */ + +/* +Real-Time Audio Call + TRTC Audio Call + This document shows how to integrate the real-time audio call feature. + 1. Switch between the speaker and receiver: [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone] + 2. Mute the device so that others won’t hear the audio of the device: [_trtcCloud muteLocalAudio:YES] + 3. Display other network and volume information: delegate -> onNetworkQuality, onUserVoiceVolume + Documentation: https://cloud.tencent.com/document/product/647/42046 +*/ + +#import "VideoCallingViewController.h" + +#import "TrtcUserInfo.h" +#import "CordovaEventKit.h" +#import "UIView+Toast.h" +#import "Events.h" +#import "UserUpdateListener.h" + + +static const NSInteger maxRemoteUserNum = 7; + +@interface VideoCallingViewController () + +@property (weak, nonatomic) IBOutlet UIButton *backButton; +@property (weak, nonatomic) IBOutlet UIButton *subVisibleButton; +@property (weak, nonatomic) IBOutlet UIButton *viewRotateButton; +@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *remoteViewArr; +@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *subViewBtnArr; +@property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *displayLabelArr; +@property (weak, nonatomic) IBOutlet UILabel *displayLabel; + +@property (assign, nonatomic) UInt32 roomId; +@property (strong, nonatomic) NSString* userId; +@property(nonatomic, assign) UInt32 sdkAppId; +@property (strong, nonatomic) NSString* userSig; +@property (strong, nonatomic) TRTCCloud *trtcCloud; +@property (strong, nonatomic) NSMutableOrderedSet *remoteUidSet; +@property (strong, nonatomic) NSMutableArray *viewUsers; + +@property (assign, nonatomic) BOOL isFrontCamera; +@property (assign, nonatomic) BOOL *hasShareUser; +@property (assign, nonatomic) BOOL *hiddenAllSubView; + +@property (assign, nonatomic) NSInteger rotation; +@end + +@implementation VideoCallingViewController + + static VideoCallingViewController* _self; + ++(VideoCallingViewController*)viewController{ + return _self; +} +- (TRTCCloud*)trtcCloud { + if (!_trtcCloud) { + _trtcCloud = [TRTCCloud sharedInstance]; + } + return _trtcCloud; +} + +- (NSMutableOrderedSet *)remoteUidSet { + if (!_remoteUidSet) { + _remoteUidSet = [[NSMutableOrderedSet alloc] initWithCapacity:maxRemoteUserNum]; + } + return _remoteUidSet; +} + +- (NSMutableArray *)viewUsers { + if (!_viewUsers) { + _viewUsers = [[NSMutableArray alloc] initWithCapacity:maxRemoteUserNum]; + } + return _viewUsers; +} + +- (instancetype)initWithRoomId:(UInt32)roomId userId:(NSString *)userId appId:(UInt32)appId userSig:(NSString *)userSig{ + NSLog(@"TRTC - initWithRoomId:::::"); + self = [super initWithNibName:NSStringFromClass([self class]) bundle:nil]; + if (self) { + _roomId = roomId; + _userId = userId; + _sdkAppId = appId; + _userSig = userSig; + } + NSLog(@"TRTC - roomid:%d,userID:%@,sdkAppid:%d,userSig:%@",_roomId,_userId,_sdkAppId,_userSig); + _self = self; + return self; +} + +- (void) updateUser:(NSDictionary*)extra{ + NSLog(@"TRTC - userinfo.update -- userID:%@,displayname:%@",extra[@"userId"],extra[@"displayName"]); + TrtcUserInfo *user = [[TrtcUserInfo alloc]initWithPersonid:extra[@"userId"]]; + NSInteger index = [[self remoteUidSet] indexOfObject: user]; + NSLog(@"TRTC - userinfo.update -- userId:%@,index:%ld",extra[@"userId"],index); + if (index == NSNotFound) { return; } + TrtcUserInfo *obj = [self remoteUidSet][index]; + [obj setDisplayName: extra[@"displayName"]]; + dispatch_async(dispatch_get_main_queue(), ^{ + [self refreshRemoteVideoViews]; + }); +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + self.isFrontCamera = NO; + self.trtcCloud.delegate = self; + + [self setupDefaultUIConfig]; + [self setupTRTCCloud]; + + [self.view sendSubviewToBack:self.view]; +} + +- (void)setupDefaultUIConfig { + NSLog(@"TRTC - setupDefaultUIConfig:::::"); + _displayLabel.text = @"我"; + _displayLabel.hidden = NO; + _rotation = 0; + [Events addListener:@"userinfo.update" listener: [[UserUpdateListener alloc] init] ]; +} + + +- (void)setupTRTCCloud { + [[self remoteUidSet] removeAllObjects]; + + [self.trtcCloud startLocalPreview:_isFrontCamera view:self.view]; + TRTCParams *params = [TRTCParams new]; + params.sdkAppId = _sdkAppId; + params.roomId = _roomId; + params.userId = _userId; + params.role = TRTCRoleAnchor; + params.userSig = _userSig; + + [self.trtcCloud enterRoom:params appScene:TRTCAppSceneVideoCall]; + + TRTCVideoEncParam *encParams = [TRTCVideoEncParam new]; + encParams.videoResolution = TRTCVideoResolution_640_360; + encParams.videoBitrate = 550; + encParams.videoFps = 15; + + [self.trtcCloud setVideoEncoderParam:encParams]; + [self.trtcCloud startLocalAudio:TRTCAudioQualityMusic]; + +} + +- (void)dealloc { + [self.trtcCloud exitRoom]; + [TRTCCloud destroySharedIntance]; +} + +- (void)changeUser:(NSInteger) a and:(NSInteger) b{ + if(a == b || a < 0 || b < 0){return;} + NSInteger x = a > b ? b : a; + NSInteger y = a > b ? a : b; + if([self remoteUidSet].count > y && x>-1){ + // 交换 + NSLog(@"TRTC - onSubViewClcik:::::Before change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]); + TrtcUserInfo* info = [self remoteUidSet][x]; + TrtcUserInfo* info2 = [self remoteUidSet][y]; + [_remoteUidSet removeObjectAtIndex:x]; + [_remoteUidSet setObject:info atIndex: y-1]; + [_remoteUidSet insertObject:info2 atIndex:x]; + NSLog(@"TRTC - onSubViewClcik:::::after change:%@,%@",[[self remoteUidSet][x] personid],[[self remoteUidSet][y] personid]); + [self refreshRemoteVideoViews]; + NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys: + [[NSString alloc] initWithFormat:@"%d",_roomId],@"room",info2.personid,@"userId", nil]; + [CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event]; + } +} + +#pragma mark - IBActions + +- (IBAction)onSubVisibleChange:(UIButton*)sender { + NSLog(@"TRTC - onSubVisibleChange:::::,before:%@",[NSNumber numberWithBool:sender.selected]); + sender.selected = !sender.selected; + NSLog(@"TRTC - onSubVisibleChange:::::,after:%@",[NSNumber numberWithBool:sender.selected]); + [self refreshRemoteVideoViews]; +} + +- (IBAction)onVideoRotate:(UIButton*)sender { + NSLog(@"TRTC - onRouteChange:::::,%@,local index: %ld",[[self remoteUidSet][0] personid],[_viewUsers indexOfObject:_userId]); + TRTCRenderParams *params = [[TRTCRenderParams alloc] init]; + + params.fillMode = TRTCVideoFillMode_Fit; + _rotation += 1; + _rotation = _rotation > 3 ? 0 : _rotation; + params.rotation = _rotation; +// [_trtcCloud stopRemoteView:[[self viewUsers][0] personid] streamType:TRTCVideoStreamTypeBig]; + [_trtcCloud setRemoteRenderParams:[[self remoteUidSet][0] personid] streamType:TRTCVideoStreamTypeBig params:params]; +// [_trtcCloud updateRemoteView:self.view streamType:TRTCVideoStreamTypeBig forUser:[[self remoteUidSet][0] personid]]; +// [_trtcCloud startRemoteView:[[self viewUsers][0] personid] streamType: TRTCVideoStreamTypeBig view:self.view]; + +} + +- (IBAction)onBackClick:(UIButton*)sender { + NSLog(@"TRTC - onBackClick:::::"); + [self.trtcCloud exitRoom]; + [TRTCCloud destroySharedIntance]; + [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (IBAction)onSwitchCameraClick:(UIButton*)sender { + NSLog(@"TRTC - onSwitchCameraClick:::::"); + _isFrontCamera = !_isFrontCamera; + [[_trtcCloud getDeviceManager] switchCamera:_isFrontCamera]; +} + + +- (IBAction)onMicCaptureClick:(UIButton*)sender { + NSLog(@"TRTC - onMicCaptureClick:::::"); + sender.selected = !sender.selected; + if ([sender isSelected]) { + [_trtcCloud muteLocalAudio:YES]; + } else { + [_trtcCloud muteLocalAudio:NO]; + } +} + +- (IBAction)onSwitchSpeakerClick:(UIButton*)sender { + NSLog(@"TRTC - onSwitchSpeakerClick:::::"); + sender.selected = !sender.selected; + if ([sender isSelected]) { + [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteEarpiece]; + } else { + [[_trtcCloud getDeviceManager] setAudioRoute:TXAudioRouteSpeakerphone]; + } +} + +- (IBAction)onSubViewClcik:(UIButton*)sender { + NSLog(@"TRTC - onSubViewClcik:::::button"); + NSInteger index = [_subViewBtnArr indexOfObject:sender]; + if (index == NSNotFound) {return;} + index = index + 1; + [self changeUser:0 and:index]; +} + + +#pragma mark - TRTCCloud Delegate + +- (void)onEnterRoom:(NSInteger) result{ + NSLog(@"TRTC - onEnterRoom, %ld",result); + [_trtcCloud startLocalPreview:_isFrontCamera view:self.view]; + // 添加本地用户到用户列表 + TrtcUserInfo *info = [[TrtcUserInfo alloc] initWithPersonid:_userId]; + [info setLocal:YES]; + NSInteger index = [[self remoteUidSet] indexOfObject:info]; + if (index != NSNotFound) { + return; + } else { + [[self remoteUidSet] addObject:info]; + } + + NSDictionary *event = [[NSDictionary alloc]initWithObjectsAndKeys: + [[NSString alloc] initWithFormat:@"%d",_roomId],@"room",_userId,@"userId", nil]; + + [CordovaEventKit fireEvent:@"onLayoutChangeMessage" obj:event]; +} + +- (void)onUserVideoAvailable:(NSString *)userId available:(BOOL)available { + NSLog(@"TRTC - onUserVideoAvailable, user:%@,available%@",userId, available ? @"YES":@"NO"); + // 添加远端用户到用户列表 + TrtcUserInfo *info = [[TrtcUserInfo alloc] initWithPersonid:userId]; + NSInteger index = [[self remoteUidSet] indexOfObject:info]; + if (available) { + if (index != NSNotFound) { return; } + if([info isShareUser]){ + _hasShareUser = YES; + } + [[self remoteUidSet] addObject:info]; + } else { + if (index == NSNotFound) { return; } + if([info isShareUser]){ + _hasShareUser = NO; + _hiddenAllSubView = NO; + } + [_trtcCloud stopRemoteView:userId streamType:TRTCVideoStreamTypeSmall]; + [[self remoteUidSet] removeObject:userId]; + } + [self refreshRemoteVideoViews]; + if(_hasShareUser){ + // 切换分享屏幕到主窗口 + [self changeUser:0 and:[[self remoteUidSet] indexOfObject:info]]; + // 隐藏所有子窗口 + _hiddenAllSubView = YES; + [self refreshRemoteVideoViews]; +// [_trtcCloud stopLocalPreview]; + } + NSDictionary *event = @{@"room": [[NSString alloc] initWithFormat:@"%d", _roomId], @"userId": userId, @"available": [NSNumber numberWithBool:available]}; + [CordovaEventKit fireEvent:@"onUserVideoAvailable" obj:event]; +} + +- (void)refreshRemoteVideoViews { + NSLog(@"TRTC - refreshRemoteVideoViews:%ld",_remoteViewArr.count); + + _subVisibleButton.hidden = _hasShareUser != nil; + _viewRotateButton.hidden = _hasShareUser == nil; + _viewRotateButton.enabled = !_viewRotateButton.hidden; + for (int i = 0; i <= _remoteViewArr.count; i++) { + TrtcUserInfo* nUser = [self remoteUidSet].count > i ? [self remoteUidSet][i] : nil; + TrtcUserInfo* oUser = [self viewUsers].count > i ? [self viewUsers][i] : nil; + UIView* view = i == 0 ? self.view : _remoteViewArr[i-1]; + UILabel* label = i ==0 ? _displayLabel : _displayLabelArr[i-1]; + UIButton* btn = i ==0 ? nil : _subViewBtnArr[i-1]; + NSLog(@"TRTC - refreshRemoteVideoViews - new : %@, o: %@",nUser == nil ? nil : [nUser personid],oUser == nil ? nil : [oUser personid]); + if((_hiddenAllSubView || ![_subVisibleButton isSelected]) && i!=0){ + [view setHidden:YES]; + [label setHidden:YES]; + }else{ + if(nUser != nil){ + if([nUser isEqual:oUser] && ![view isHidden]){ + if([nUser isLocalUser]){ + [label setText:@"我"]; + } else if([nUser displayName] == nil || [nUser displayName].length == 0) { + [label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]]; + } else { + [label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]]; + } + [label sizeToFit]; + continue; + } + TRTCRenderParams *params = [[TRTCRenderParams alloc] init]; + params.rotation = 0; + params.fillMode = [nUser isShareUser] ? TRTCVideoFillMode_Fit : TRTCVideoFillMode_Fill; + if([nUser isLocalUser]){ + [_trtcCloud startLocalPreview:_isFrontCamera view:view]; + [_trtcCloud setLocalRenderParams:params]; + [label setText:@"我"]; + [label sizeToFit]; + } else { + [_trtcCloud setRemoteRenderParams:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall params:params]; + [_trtcCloud startRemoteView:[nUser personid] streamType:i == 0 ? TRTCVideoStreamTypeBig : TRTCVideoStreamTypeSmall view:view]; + + if([nUser displayName] == nil || [nUser displayName].length == 0) { + [label setText:[NSString stringWithFormat:@"%@%@",[nUser personid], [nUser isShareUser] ? @"的屏幕分享" : @""]]; + } else { + [label setText:[NSString stringWithFormat:@"%@%@",[nUser displayName], [nUser isShareUser] ? @"的屏幕分享" : @""]]; + } + [label sizeToFit]; + } + [label setHidden:NO]; + [view setHidden:NO]; + if(btn != nil){ + [btn setHidden:NO]; + } + } else { + [view setHidden:YES]; + [label setHidden:YES]; + if(btn != nil){ + [btn setHidden:YES]; + } + } + } + if(nUser != nil){ + [self viewUsers].count > i ? [self viewUsers][i] = nUser : [[self viewUsers] addObject:nUser]; + }else { + while([self viewUsers].count > i){ + [[self viewUsers] removeObjectAtIndex:i]; + } + } + } +} + +- (void) onError:(TXLiteAVError)errCode errMsg:(NSString *)errMsg extInfo:(NSDictionary *)extInfo{ + NSLog(@"TRTC - onError::sdk callback onError code: %d,msg: %@,extInfo: %@",errCode,errMsg,extInfo); + dispatch_async(dispatch_get_main_queue(), ^{ + [self.view makeToast: [[NSString alloc] initWithFormat:@"%@[%d]",errMsg,errCode]]; + }); +// [self.trtcCloud exitRoom]; +// [TRTCCloud destroySharedIntance]; +// [self dismissViewControllerAnimated:YES completion:nil]; +} + +- (void) onExitRoom:(NSInteger)reason{ + if (reason == 2) { + dispatch_async(dispatch_get_main_queue(), ^{ + [self.view makeToast: @"远程协助已结束"]; + }); + } + [self dismissViewControllerAnimated:YES completion:nil]; +} + +@end diff --git a/src/ios/VideoCallingViewController.xib b/src/ios/VideoCallingViewController.xib new file mode 100755 index 0000000..60fbb93 --- /dev/null +++ b/src/ios/VideoCallingViewController.xib @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ios/libs/.gitkeep b/src/ios/libs/.gitkeep deleted file mode 100644 index f2b04b1..0000000 --- a/src/ios/libs/.gitkeep +++ /dev/null @@ -1,4 +0,0 @@ -# AVSDK -# BeautySDK -# ILiveSDK -# IMSDK diff --git a/src/ios/res/beauty-dis.png b/src/ios/res/beauty-dis.png deleted file mode 100644 index 3f709c7..0000000 Binary files a/src/ios/res/beauty-dis.png and /dev/null differ diff --git a/src/ios/res/beauty.png b/src/ios/res/beauty.png deleted file mode 100644 index b38bff1..0000000 Binary files a/src/ios/res/beauty.png and /dev/null differ diff --git a/src/ios/res/bg.png b/src/ios/res/bg.png deleted file mode 100644 index 26fc385..0000000 Binary files a/src/ios/res/bg.png and /dev/null differ diff --git a/src/ios/res/camera-gray.png b/src/ios/res/camera-gray.png deleted file mode 100644 index 5a0086b..0000000 Binary files a/src/ios/res/camera-gray.png and /dev/null differ diff --git a/src/ios/res/camera.png b/src/ios/res/camera.png deleted file mode 100644 index 424a2ee..0000000 Binary files a/src/ios/res/camera.png and /dev/null differ diff --git a/src/ios/res/chat.png b/src/ios/res/chat.png deleted file mode 100644 index 426ce06..0000000 Binary files a/src/ios/res/chat.png and /dev/null differ diff --git a/src/ios/res/doubleroom.png b/src/ios/res/doubleroom.png deleted file mode 100644 index 3ab3329..0000000 Binary files a/src/ios/res/doubleroom.png and /dev/null differ diff --git a/src/ios/res/feedback.png b/src/ios/res/feedback.png deleted file mode 100644 index 8c52b22..0000000 Binary files a/src/ios/res/feedback.png and /dev/null differ diff --git a/src/ios/res/ic_toast_success@2x.png b/src/ios/res/ic_toast_success@2x.png deleted file mode 100644 index e46d177..0000000 Binary files a/src/ios/res/ic_toast_success@2x.png and /dev/null differ diff --git a/src/ios/res/icon_sign@2x.png b/src/ios/res/icon_sign@2x.png deleted file mode 100644 index 0f8f7ef..0000000 Binary files a/src/ios/res/icon_sign@2x.png and /dev/null differ diff --git a/src/ios/res/log.png b/src/ios/res/log.png deleted file mode 100644 index 9435fa3..0000000 Binary files a/src/ios/res/log.png and /dev/null differ diff --git a/src/ios/res/log2.png b/src/ios/res/log2.png deleted file mode 100644 index 012a5c7..0000000 Binary files a/src/ios/res/log2.png and /dev/null differ diff --git a/src/ios/res/mic-dis.png b/src/ios/res/mic-dis.png deleted file mode 100644 index d948549..0000000 Binary files a/src/ios/res/mic-dis.png and /dev/null differ diff --git a/src/ios/res/mic.png b/src/ios/res/mic.png deleted file mode 100644 index 7390460..0000000 Binary files a/src/ios/res/mic.png and /dev/null differ diff --git a/src/ios/res/muti_room_bg.png b/src/ios/res/muti_room_bg.png deleted file mode 100644 index 90b77b9..0000000 Binary files a/src/ios/res/muti_room_bg.png and /dev/null differ diff --git a/src/ios/res/role.png b/src/ios/res/role.png deleted file mode 100644 index f25c11b..0000000 Binary files a/src/ios/res/role.png and /dev/null differ diff --git a/src/ios/res/ui_title_arrow_left.png b/src/ios/res/ui_title_arrow_left.png deleted file mode 100644 index 065336e..0000000 Binary files a/src/ios/res/ui_title_arrow_left.png and /dev/null differ