WFCUFloatingWindow.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. //
  2. // WFCUFloatingWindow.m
  3. // WFDemo
  4. //
  5. // Created by heavyrain on 17/9/27.
  6. // Copyright © 2017年 WildFireChat. All rights reserved.
  7. //
  8. #if WFCU_SUPPORT_VOIP
  9. #import "WFCUFloatingWindow.h"
  10. #import <CoreTelephony/CTCall.h>
  11. #import <CoreTelephony/CTCallCenter.h>
  12. #import <UIKit/UIKit.h>
  13. #import "WFCUConferenceManager.h"
  14. #import "WFCUConfigManager.h"
  15. #import "WFCUImage.h"
  16. #import "WFZConferenceInfo.h"
  17. @interface WFCUFloatingWindow () <WFAVCallSessionDelegate, WFCUConferenceManagerDelegate>
  18. @property(nonatomic, strong) NSTimer *activeTimer;
  19. @property(nonatomic, copy) void (^touchedBlock)(WFAVCallSession *callSession, WFZConferenceInfo *conferenceInfo);
  20. @property(nonatomic, strong) CTCallCenter *callCenter;
  21. @property(nonatomic, strong) WFAVParticipantProfile *focusUserProfile;
  22. @property(nonatomic, assign)CGFloat winWidth;
  23. @property(nonatomic, assign)CGFloat winHeight;
  24. @property(nonatomic, strong)NSTimer *broadcastOngoingTimer;
  25. @end
  26. static WFCUFloatingWindow *staticWindow = nil;
  27. static NSString *kFloatingWindowPosX = @"kFloatingWindowPosX";
  28. static NSString *kFloatingWindowPosY = @"kFloatingWindowPosY";
  29. @implementation WFCUFloatingWindow
  30. + (void)startCallFloatingWindow:(WFAVCallSession *)callSession focusUser:(WFAVParticipantProfile *)focusUserProfile
  31. withTouchedBlock:(void (^)(WFAVCallSession *callSession, WFZConferenceInfo *conferenceInfo))touchedBlock {
  32. staticWindow = [[WFCUFloatingWindow alloc] init];
  33. staticWindow.callSession = callSession;
  34. [staticWindow.callSession setDelegate:staticWindow];
  35. staticWindow.touchedBlock = touchedBlock;
  36. staticWindow.focusUserProfile = focusUserProfile;
  37. [staticWindow initWindow];
  38. if(callSession.isConference) {
  39. [callSession.participants enumerateObjectsUsingBlock:^(WFAVParticipantProfile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  40. if([obj.userId isEqualToString:focusUserProfile.userId] && obj.screeSharing == focusUserProfile.screeSharing) {
  41. [callSession setParticipant:obj.userId screenSharing:obj.screeSharing videoType:WFAVVideoType_SmallStream];
  42. } else {
  43. [callSession setParticipant:obj.userId screenSharing:obj.screeSharing videoType:WFAVVideoType_None];
  44. }
  45. }];
  46. }
  47. }
  48. + (void)stopCallFloatingWindow {
  49. [staticWindow hideCallFloatingWindow];
  50. [staticWindow clearCallFloatingWindow];
  51. staticWindow = nil;
  52. }
  53. - (void)initWindow {
  54. if (self.callSession.state == kWFAVEngineStateIdle) {
  55. [self performSelector:@selector(clearCallFloatingWindow) withObject:nil afterDelay:2];
  56. }
  57. [self updateActiveTimer];
  58. [self startActiveTimer];
  59. [self updateWindow];
  60. [self registerTelephonyEvent];
  61. [[NSNotificationCenter defaultCenter] addObserver:self
  62. selector:@selector(onDeviceOrientationDidChange:)
  63. name:UIDeviceOrientationDidChangeNotification
  64. object:nil];
  65. [self addProximityMonitoringObserver];
  66. [WFCUConferenceManager sharedInstance].delegate = self;
  67. if(!self.callSession.isConference) {
  68. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onReceiveMessages:) name:kReceiveMessages object:nil];
  69. }
  70. if(!self.callSession.isConference) {
  71. if(self.callSession.state == kWFAVEngineStateConnected && [self.callSession.initiator isEqualToString:[WFCCNetworkService sharedInstance].userId]) {
  72. [self startBroadcastCallOngoing:YES];
  73. } else {
  74. [self startBroadcastCallOngoing:NO];
  75. }
  76. }
  77. }
  78. - (void)onReceiveMessages:(NSNotification *)notification {
  79. NSArray<WFCCMessage *> *messages = notification.object;
  80. for (WFCCMessage *msg in messages) {
  81. if([msg.content isKindOfClass:WFCCJoinCallRequestMessageContent.class]) {
  82. WFCCJoinCallRequestMessageContent *join = (WFCCJoinCallRequestMessageContent *)msg.content;
  83. if([self.callSession.callId isEqualToString:join.callId] && self.callSession.state == kWFAVEngineStateConnected && [self.callSession.initiator isEqualToString:[WFCCNetworkService sharedInstance].userId]) {
  84. [self.callSession inviteNewParticipants:@[msg.fromUser] targetClientId:join.clientId autoAnswer:YES];
  85. }
  86. }
  87. }
  88. }
  89. - (void)didMoveToParentViewController:(UIViewController *)parent {
  90. [self startBroadcastCallOngoing:NO];
  91. }
  92. - (void)startBroadcastCallOngoing:(BOOL)start {
  93. if([WFCUConfigManager globalManager].enableMultiCallAutoJoin) {
  94. if(start && !self.broadcastOngoingTimer) {
  95. __weak typeof(self)ws = self;
  96. WFCCMultiCallOngoingMessageContent *ongoing = [[WFCCMultiCallOngoingMessageContent alloc] init];
  97. ongoing.callId = self.callSession.callId;
  98. ongoing.audioOnly = self.callSession.audioOnly;
  99. ongoing.initiator = self.callSession.initiator;
  100. ongoing.targetIds = self.callSession.participantIds;
  101. if (@available(iOS 10.0, *)) {
  102. self.broadcastOngoingTimer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
  103. typeof(self) strongSelf = ws;
  104. if(strongSelf.callSession.state == kWFAVEngineStateConnected) {
  105. [[WFCCIMService sharedWFCIMService] send:strongSelf.callSession.conversation content:ongoing success:nil error:nil];
  106. }
  107. }];
  108. } else {
  109. // Fallback on earlier versions
  110. }
  111. } else if(!start && self.broadcastOngoingTimer) {
  112. [self.broadcastOngoingTimer invalidate];
  113. self.broadcastOngoingTimer = nil;
  114. }
  115. }
  116. }
  117. - (void)registerTelephonyEvent {
  118. self.callCenter = [[CTCallCenter alloc] init];
  119. __weak __typeof(self) weakSelf = self;
  120. self.callCenter.callEventHandler = ^(CTCall *call) {
  121. if ([call.callState isEqualToString:CTCallStateConnected]) {
  122. [weakSelf.callSession endCall];
  123. }
  124. };
  125. }
  126. - (void)onDeviceOrientationDidChange:(NSNotification *)notification {
  127. [self updateWindow];
  128. }
  129. - (void)startActiveTimer {
  130. self.activeTimer = [NSTimer scheduledTimerWithTimeInterval:1
  131. target:self
  132. selector:@selector(updateActiveTimer)
  133. userInfo:nil
  134. repeats:YES];
  135. [self.activeTimer fire];
  136. }
  137. - (void)stopActiveTimer {
  138. if (self.activeTimer) {
  139. [self.activeTimer invalidate];
  140. self.activeTimer = nil;
  141. }
  142. }
  143. - (void)updateActiveTimer {
  144. long sec = [[NSDate date] timeIntervalSince1970] - self.callSession.connectedTime / 1000;
  145. if (self.callSession.state == kWFAVEngineStateConnected && ![self isVideoViewEnabled]) {
  146. NSString *timeStr;
  147. if (sec < 60 * 60) {
  148. timeStr = [NSString stringWithFormat:@"%02ld:%02ld", sec / 60, sec % 60];
  149. } else {
  150. timeStr = [NSString stringWithFormat:@"%02ld:%02ld:%02ld", sec / 60 / 60, (sec / 60) % 60, sec % 60];
  151. }
  152. BOOL showFloatingButton = NO;
  153. if (!self.floatingButton.titleLabel.text) {
  154. self.floatingButton.hidden = YES;
  155. showFloatingButton = YES;
  156. }
  157. [self.floatingButton setTitle:timeStr forState:UIControlStateNormal];
  158. [self layoutTimeText:self.floatingButton];
  159. if (showFloatingButton) {
  160. dispatch_async(dispatch_get_main_queue(), ^{
  161. [self.floatingButton setTitle:timeStr forState:UIControlStateNormal];
  162. [self layoutTimeText:self.floatingButton];
  163. self.floatingButton.hidden = NO;
  164. });
  165. }
  166. }
  167. }
  168. //1.决定当前界面是否开启自动转屏,如果返回NO,后面两个方法也不会被调用,只是会支持默认的方向
  169. - (BOOL)shouldAutorotate {
  170. return YES;
  171. }
  172. //2.返回支持的旋转方向
  173. //iPad设备上,默认返回值UIInterfaceOrientationMaskAllButUpSideDwon
  174. //iPad设备上,默认返回值是UIInterfaceOrientationMaskAll
  175. - (UIInterfaceOrientationMask)supportedInterfaceOrientations{
  176. return UIDeviceOrientationLandscapeLeft | UIDeviceOrientationLandscapeRight | UIDeviceOrientationPortrait;
  177. }
  178. //3.返回进入界面默认显示方向
  179. - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
  180. return UIInterfaceOrientationPortrait;
  181. }
  182. - (void)updateWindow {
  183. CGFloat posX = [[[NSUserDefaults standardUserDefaults] objectForKey:kFloatingWindowPosX] floatValue];
  184. CGFloat posY = [[[NSUserDefaults standardUserDefaults] objectForKey:kFloatingWindowPosY] floatValue];
  185. posX = posX ? posX : 30;
  186. posY = posY ? posY : 30;
  187. CGRect screenBounds = [UIScreen mainScreen].bounds;
  188. posX = (posX + 30) > screenBounds.size.width ? (screenBounds.size.width - 30) : posX;
  189. posY = (posY + 48) > screenBounds.size.height ? (screenBounds.size.height - 48) : posY;
  190. if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) {
  191. self.window.transform = CGAffineTransformMakeRotation(M_PI / 2);
  192. self.window.frame = CGRectMake(posX, posY, 64, 96);
  193. self.floatingButton.frame = CGRectMake(0, 0, 96, 64);
  194. if ([self isVideoViewEnabled]) {
  195. self.videoView.frame = CGRectMake(0, 0, 96, 64);
  196. }
  197. } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) {
  198. self.window.transform = CGAffineTransformMakeRotation(-M_PI / 2);
  199. self.window.frame = CGRectMake(posX, posY, 64, 96);
  200. self.floatingButton.frame = CGRectMake(0, 0, 96, 64);
  201. if ([self isVideoViewEnabled]) {
  202. self.videoView.frame = CGRectMake(0, 0, 96, 64);
  203. }
  204. } else {
  205. if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) {
  206. self.window.transform = CGAffineTransformMakeRotation(M_PI);
  207. } else {
  208. self.window.transform = CGAffineTransformMakeRotation(0);
  209. }
  210. self.window.frame = CGRectMake(posX, posY, 64, 96);
  211. self.floatingButton.frame = CGRectMake(0, 0, 64, 96);
  212. if ([self isVideoViewEnabled]) {
  213. self.videoView.frame = CGRectMake(0, 0, 64, 96);
  214. }
  215. }
  216. if(self.callSession.isInAppScreenSharing) {
  217. self.window.frame = CGRectMake(posX, posY, 64, 64);
  218. self.window.layer.cornerRadius = 32;
  219. self.window.layer.masksToBounds = YES;
  220. self.floatingButton.frame = CGRectMake(0, 0, 64, 64);
  221. self.floatingButton.layer.cornerRadius = 32;
  222. self.floatingButton.layer.masksToBounds = YES;
  223. [self.floatingButton setTitle:WFCString(@"EndSharing") forState:UIControlStateNormal];
  224. [self.floatingButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
  225. [self.floatingButton setBackgroundColor:[UIColor redColor]];
  226. self.videoView.hidden = YES;
  227. } else if ([self isVideoViewEnabled]) {
  228. if (self.callSession.state == kWFAVEngineStateIncomming) {
  229. [self.floatingButton setTitle:WFCString(@"WaitAnwser") forState:UIControlStateNormal];
  230. self.videoView.hidden = YES;
  231. } else if (self.callSession.state == kWFAVEngineStateOutgoing) {
  232. self.videoView.hidden = NO;
  233. [self.floatingButton setTitle:@"" forState:UIControlStateNormal];
  234. [self.callSession setupLocalVideoView:self.videoView scalingType:kWFAVVideoScalingTypeAspectFit];
  235. } else if (self.callSession.state == kWFAVEngineStateConnected) {
  236. self.videoView.hidden = NO;
  237. [self.floatingButton setTitle:@"" forState:UIControlStateNormal];
  238. NSString *focusUserId;
  239. BOOL screenSharing = NO;
  240. if([self.focusUserProfile isKindOfClass:[NSString class]]) {
  241. focusUserId = (NSString *)self.focusUserProfile;
  242. } else {
  243. focusUserId = self.focusUserProfile.userId;
  244. screenSharing = self.focusUserProfile.screeSharing;
  245. }
  246. if ([focusUserId isEqualToString:[WFCCNetworkService sharedInstance].userId]) {
  247. [self.callSession setupLocalVideoView:self.videoView scalingType:kWFAVVideoScalingTypeAspectFit];
  248. } else {
  249. [self.callSession setupRemoteVideoView:self.videoView scalingType:kWFAVVideoScalingTypeAspectFit forUser:focusUserId screenSharing:screenSharing];
  250. }
  251. [self updateVideoView];
  252. } else if (self.callSession.state == kWFAVEngineStateIdle) {
  253. UILabel *videoStopTips =
  254. [[UILabel alloc] initWithFrame:CGRectMake(0, self.videoView.frame.size.height / 2 - 10,
  255. self.videoView.frame.size.width, 20)];
  256. videoStopTips.textAlignment = NSTextAlignmentCenter;
  257. videoStopTips.text = WFCString(@"Ended");
  258. videoStopTips.textColor = HEXCOLOR(0x0195ff);
  259. [self.videoView addSubview:videoStopTips];
  260. } else { //connecting...
  261. self.videoView.hidden = NO;
  262. [self.floatingButton setTitle:@"" forState:UIControlStateNormal];
  263. }
  264. } else {
  265. if (self.callSession.state == kWFAVEngineStateIdle) {
  266. [self.floatingButton setBackgroundColor:[UIColor clearColor]];
  267. [self.floatingButton setTitle:WFCString(@"Ended")
  268. forState:UIControlStateNormal];
  269. } else {
  270. if (self.callSession.state == kWFAVEngineStateOutgoing) {
  271. [self.floatingButton setTitle:WFCString(@"WaitAnwser") forState:UIControlStateNormal];
  272. } else if (self.callSession.state == kWFAVEngineStateIncomming) {
  273. [self.floatingButton setTitle:WFCString(@"WaitAnwser") forState:UIControlStateNormal];
  274. } else {
  275. [self.floatingButton setTitle:@"" forState:UIControlStateNormal];
  276. [self.floatingButton setImage:[WFCUImage imageNamed:@"floatingaudio"]
  277. forState:UIControlStateNormal];
  278. }
  279. }
  280. }
  281. }
  282. - (void)updateVideoView {
  283. __block BOOL isMuted = NO;
  284. NSString *focusUserId;
  285. BOOL screenSharing = NO;
  286. if([self.focusUserProfile isKindOfClass:[NSString class]]) {
  287. focusUserId = (NSString *)self.focusUserProfile;
  288. } else {
  289. focusUserId = self.focusUserProfile.userId;
  290. screenSharing = self.focusUserProfile.screeSharing;
  291. }
  292. if ([focusUserId isEqualToString:[WFCCNetworkService sharedInstance].userId]) {
  293. isMuted = [WFAVEngineKit sharedEngineKit].currentSession.isVideoMuted;
  294. } else {
  295. [[[WFAVEngineKit sharedEngineKit].currentSession participants] enumerateObjectsUsingBlock:^(WFAVParticipantProfile * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  296. if([obj.userId isEqual:focusUserId] && obj.screeSharing == screenSharing) {
  297. isMuted = obj.videoMuted;
  298. *stop = YES;
  299. }
  300. }];
  301. }
  302. if(isMuted) {
  303. [self.floatingButton setTitle:WFCString(@"CloseVideo")
  304. forState:UIControlStateNormal];
  305. self.videoView.hidden = YES;
  306. } else {
  307. self.videoView.hidden = NO;
  308. }
  309. }
  310. - (UIWindow *)window {
  311. if (!_window) {
  312. CGFloat posX = [[[NSUserDefaults standardUserDefaults] objectForKey:kFloatingWindowPosX] floatValue];
  313. CGFloat posY = [[[NSUserDefaults standardUserDefaults] objectForKey:kFloatingWindowPosY] floatValue];
  314. posX = (posX - 30) ? posX : 30;
  315. posY = (posY - 48) ? posY : 48;
  316. CGRect screenBounds = [UIScreen mainScreen].bounds;
  317. posX = (posX + 30) > screenBounds.size.width ? (screenBounds.size.width - 30) : posX;
  318. posY = (posY + 48) > screenBounds.size.height ? (screenBounds.size.height - 48) : posY;
  319. _window = [[UIWindow alloc] initWithFrame:CGRectMake(posX, posY, 64, 96)];
  320. _window.backgroundColor = [UIColor whiteColor];
  321. _window.windowLevel = UIWindowLevelAlert + 1;
  322. _window.layer.cornerRadius = 4;
  323. _window.layer.masksToBounds = YES;
  324. _window.layer.borderWidth = 1;
  325. _window.layer.borderColor = [HEXCOLOR(0x0A88E1) CGColor];
  326. [_window makeKeyAndVisible]; //关键语句,显示window
  327. UIPanGestureRecognizer *panGestureRecognizer =
  328. [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGestures:)];
  329. panGestureRecognizer.minimumNumberOfTouches = 1;
  330. panGestureRecognizer.maximumNumberOfTouches = 1;
  331. [_window addGestureRecognizer:panGestureRecognizer];
  332. }
  333. return _window;
  334. }
  335. - (UIView *)videoView {
  336. if (!_videoView) {
  337. _videoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 64, 96)];
  338. _videoView.backgroundColor = [UIColor blackColor];
  339. CGRect windowFrame = self.window.frame;
  340. windowFrame.size.width = _videoView.frame.size.width;
  341. windowFrame.size.height = _videoView.frame.size.height;
  342. self.window.frame = windowFrame;
  343. [self.window addSubview:_videoView];
  344. UITapGestureRecognizer *tap =
  345. [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(touchedWindow:)];
  346. [_videoView addGestureRecognizer:tap];
  347. }
  348. return _videoView;
  349. }
  350. - (UIButton *)floatingButton {
  351. if (!_floatingButton) {
  352. _floatingButton = [UIButton buttonWithType:UIButtonTypeCustom];
  353. [_floatingButton setTitle:@"" forState:UIControlStateNormal];
  354. _floatingButton.backgroundColor = [UIColor clearColor];
  355. _floatingButton.frame = CGRectMake(0, 0, 64, 96);
  356. [_floatingButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
  357. _floatingButton.titleLabel.font = [UIFont systemFontOfSize:14];
  358. CGRect windowFrame = self.window.frame;
  359. windowFrame.size.width = _floatingButton.frame.size.width;
  360. windowFrame.size.height = _floatingButton.frame.size.height;
  361. self.window.frame = windowFrame;
  362. [_floatingButton addTarget:self action:@selector(touchedWindow:) forControlEvents:UIControlEventTouchUpInside];
  363. [self.window addSubview:_floatingButton];
  364. }
  365. return _floatingButton;
  366. }
  367. - (void)handlePanGestures:(UIPanGestureRecognizer *)paramSender {
  368. if (paramSender.state != UIGestureRecognizerStateEnded && paramSender.state != UIGestureRecognizerStateFailed) {
  369. CGPoint location = [paramSender locationInView:[UIApplication sharedApplication].windows[0]];
  370. if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeLeft) {
  371. CGFloat tmp = location.x;
  372. location.x = [UIScreen mainScreen].bounds.size.height - location.y;
  373. location.y = tmp;
  374. } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) {
  375. CGFloat tmp = location.x;
  376. location.x = location.y;
  377. location.y = [UIScreen mainScreen].bounds.size.width - tmp;
  378. } else if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortraitUpsideDown) {
  379. CGFloat tmp = location.x;
  380. location.x = [UIScreen mainScreen].bounds.size.height - location.y;
  381. location.y = [UIScreen mainScreen].bounds.size.width - tmp;
  382. }
  383. CGRect frame = self.window.frame;
  384. frame.origin.x = location.x - frame.size.width / 2;
  385. frame.origin.y = location.y - frame.size.height / 2;
  386. if (frame.origin.x < 0) {
  387. frame.origin.x = 2;
  388. }
  389. if (frame.origin.y < 0) {
  390. frame.origin.y = 2;
  391. }
  392. CGRect screenBounds = [UIScreen mainScreen].bounds;
  393. BOOL isLandscape = screenBounds.size.width > screenBounds.size.height;
  394. if (isLandscape) {
  395. if (frame.origin.y + frame.size.height > [UIScreen mainScreen].bounds.size.width) {
  396. frame.origin.y = [UIScreen mainScreen].bounds.size.width - 2 - frame.size.height;
  397. }
  398. if (frame.origin.x + frame.size.width > [UIScreen mainScreen].bounds.size.height) {
  399. frame.origin.x = [UIScreen mainScreen].bounds.size.height - 2 - frame.size.width;
  400. }
  401. } else {
  402. if (frame.origin.x + frame.size.width > [UIScreen mainScreen].bounds.size.width) {
  403. frame.origin.x = [UIScreen mainScreen].bounds.size.width - 2 - frame.size.width;
  404. }
  405. if (frame.origin.y + frame.size.height > [UIScreen mainScreen].bounds.size.height) {
  406. frame.origin.y = [UIScreen mainScreen].bounds.size.height - 2 - frame.size.height;
  407. }
  408. }
  409. self.window.frame = frame;
  410. } else if (paramSender.state == UIGestureRecognizerStateEnded) {
  411. CGRect frame = self.window.frame;
  412. [[NSUserDefaults standardUserDefaults] setObject:@(frame.origin.x) forKey:kFloatingWindowPosX];
  413. [[NSUserDefaults standardUserDefaults] setObject:@(frame.origin.y) forKey:kFloatingWindowPosY];
  414. [[NSUserDefaults standardUserDefaults] synchronize];
  415. }
  416. }
  417. - (void)touchedWindow:(id)sender {
  418. if(self.callSession.isInAppScreenSharing) {
  419. [self.callSession setInAppScreenSharing:NO];
  420. }
  421. [self hideCallFloatingWindow];
  422. if (self.touchedBlock) {
  423. self.touchedBlock(self.callSession, [WFCUConferenceManager sharedInstance].currentConferenceInfo);
  424. }
  425. [self clearCallFloatingWindow];
  426. }
  427. - (void)hideCallFloatingWindow {
  428. [self stopActiveTimer];
  429. if (_videoView) {
  430. [_videoView removeFromSuperview];
  431. _videoView = nil;
  432. }
  433. if (_floatingButton) {
  434. [_floatingButton removeFromSuperview];
  435. _floatingButton = nil;
  436. }
  437. [_window setHidden:YES];
  438. }
  439. - (void)clearCallFloatingWindow {
  440. [[NSNotificationCenter defaultCenter] removeObserver:self];
  441. _activeTimer = nil;
  442. _callSession = nil;
  443. _touchedBlock = nil;
  444. _floatingButton = nil;
  445. _videoView = nil;
  446. _window = nil;
  447. staticWindow = nil;
  448. }
  449. - (void)layoutTimeText:(UIButton *)button {
  450. // button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
  451. [button.titleLabel setFont:[UIFont systemFontOfSize:16]];
  452. [button setTitleColor:HEXCOLOR(0x0195ff) forState:UIControlStateNormal];
  453. //top left buttom right
  454. button.titleEdgeInsets = UIEdgeInsetsMake(button.imageView.frame.size.height / 2, -button.imageView.frame.size.width,
  455. -button.imageView.frame.size.height, 0);
  456. button.imageEdgeInsets = UIEdgeInsetsMake(0,
  457. 0, button.imageView.frame.size.height / 2, -button.titleLabel.bounds.size.width);
  458. }
  459. - (BOOL)isVideoViewEnabled {
  460. return !self.callSession.isAudioOnly;
  461. }
  462. #pragma mark - WFAVCallSessionDelegate
  463. - (void)didChangeState:(WFAVEngineState)state {
  464. switch (state) {
  465. case kWFAVEngineStateIdle:
  466. [self updateWindow];
  467. [self performSelector:@selector(clearCallFloatingWindow) withObject:nil afterDelay:2];
  468. [self removeProximityMonitoringObserver];
  469. break;
  470. case kWFAVEngineStateConnected:
  471. [self updateWindow];
  472. break;
  473. default:
  474. [self updateWindow];
  475. break;
  476. }
  477. if(!self.callSession.isConference) {
  478. if(state == kWFAVEngineStateConnected && [self.callSession.initiator isEqualToString:[WFCCNetworkService sharedInstance].userId]) {
  479. [self startBroadcastCallOngoing:YES];
  480. } else {
  481. [self startBroadcastCallOngoing:NO];
  482. }
  483. }
  484. }
  485. - (void)didCallEndWithReason:(WFAVCallEndReason)reason {
  486. if(self.callSession.isConference) {
  487. [[WFCUConferenceManager sharedInstance] addHistory:[WFCUConferenceManager sharedInstance].currentConferenceInfo duration:(int)([WFAVEngineKit sharedEngineKit].currentSession.endTime - [WFAVEngineKit sharedEngineKit].currentSession.startTime)];
  488. }
  489. }
  490. - (void)didParticipantJoined:(NSString *)userId screenSharing:(BOOL)screenSharing {
  491. }
  492. - (void)didParticipantConnected:(NSString *)userId screenSharing:(BOOL)screenSharing {
  493. }
  494. - (void)didParticipantLeft:(NSString *)userId screenSharing:(BOOL)screenSharing withReason:(WFAVCallEndReason)reason {
  495. }
  496. - (void)didError:(NSError *)error {
  497. }
  498. - (void)didGetStats:(NSArray *)stats {
  499. }
  500. - (void)didChangeAudioRoute {
  501. }
  502. - (void)didCreateLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
  503. }
  504. - (void)didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack fromUser:(NSString *)userId screenSharing:(BOOL)screenSharing {
  505. }
  506. - (void)didVideoMuted:(BOOL)videoMuted fromUser:(NSString *)userId {
  507. }
  508. - (void)didReportAudioVolume:(NSInteger)volume ofUser:(NSString *)userId {
  509. }
  510. - (void)didChangeMode:(BOOL)isAudioOnly {
  511. [self.videoView removeFromSuperview];
  512. [self initWindow];
  513. }
  514. - (void)didChangeInitiator:(NSString * _Nullable)initiator {
  515. if(!self.callSession.isConference) {
  516. [self startBroadcastCallOngoing:[initiator isEqualToString:[WFCCNetworkService sharedInstance].userId]];
  517. }
  518. }
  519. - (void)didMuteStateChanged:(NSArray<NSString *> *)userIds {
  520. if(![WFAVEngineKit sharedEngineKit].currentSession.isAudioOnly) {
  521. [self updateVideoView];
  522. }
  523. }
  524. - (void)addProximityMonitoringObserver {
  525. [UIDevice currentDevice].proximityMonitoringEnabled = YES;
  526. [[NSNotificationCenter defaultCenter] addObserver:self
  527. selector:@selector(proximityStatueChanged:)
  528. name:UIDeviceProximityStateDidChangeNotification
  529. object:nil];
  530. }
  531. - (void)removeProximityMonitoringObserver {
  532. [UIDevice currentDevice].proximityMonitoringEnabled = NO;
  533. [[NSNotificationCenter defaultCenter] removeObserver:self
  534. name:UIDeviceProximityStateDidChangeNotification
  535. object:nil];
  536. }
  537. - (void)proximityStatueChanged:(NSNotificationCenter *)notification {
  538. }
  539. - (void)onChangeModeRequest:(BOOL)isAudience {
  540. if(isAudience) {
  541. [[WFAVEngineKit sharedEngineKit].currentSession switchAudience:isAudience];
  542. } else {
  543. //Todo 该怎么处理?
  544. }
  545. }
  546. @end
  547. #endif