diff --git a/VideoCalls/CallViewController.h b/VideoCalls/CallViewController.h index 4ca0f6d4..62156a11 100644 --- a/VideoCalls/CallViewController.h +++ b/VideoCalls/CallViewController.h @@ -28,6 +28,6 @@ @property (nonatomic, strong) IBOutlet UIImageView *waitingImageView; @property (nonatomic, strong) IBOutlet UILabel *waitingLabel; -- (instancetype)initCallInRoom:(NCRoom *)room asUser:(NSString*)displayName; +- (instancetype)initCallInRoom:(NCRoom *)room asUser:(NSString*)displayName audioOnly:(BOOL)audioOnly; @end diff --git a/VideoCalls/CallViewController.m b/VideoCalls/CallViewController.m index 8bb66ed6..6be83506 100644 --- a/VideoCalls/CallViewController.m +++ b/VideoCalls/CallViewController.m @@ -34,6 +34,7 @@ typedef NS_ENUM(NSInteger, CallState) { NCCallController *_callController; ARDCaptureController *_captureController; NSTimer *_detailedViewTimer; + BOOL _isAudioOnly; BOOL _userDisabledVideo; } @@ -51,17 +52,18 @@ typedef NS_ENUM(NSInteger, CallState) { @synthesize delegate = _delegate; -- (instancetype)initCallInRoom:(NCRoom *)room asUser:(NSString*)displayName +- (instancetype)initCallInRoom:(NCRoom *)room asUser:(NSString*)displayName audioOnly:(BOOL)audioOnly { self = [super init]; if (!self) { return nil; } - _callController = [[NCCallController alloc] initWithDelegate:self]; + _callController = [[NCCallController alloc] initWithDelegate:self forAudioOnlyCall:audioOnly]; _callController.room = room; _callController.userDisplayName = displayName; _room = room; + _isAudioOnly = audioOnly; _peersInCall = [[NSMutableArray alloc] init]; _renderersDict = [[NSMutableDictionary alloc] init]; @@ -94,7 +96,7 @@ typedef NS_ENUM(NSInteger, CallState) { [self setWaitingScreen]; - if ([[[NCSettingsController sharedInstance] videoSettingsModel] videoDisabledSettingFromStore]) { + if ([[[NCSettingsController sharedInstance] videoSettingsModel] videoDisabledSettingFromStore] || _isAudioOnly) { _userDisabledVideo = YES; [self disableLocalVideo]; } @@ -342,7 +344,7 @@ typedef NS_ENUM(NSInteger, CallState) { [cell setUserAvatar:[_callController getUserIdFromSessionId:peerConnection.peerId]]; [cell setDisplayName:peerConnection.peerName]; [cell setAudioDisabled:peerConnection.isRemoteAudioDisabled]; - [cell setVideoDisabled:peerConnection.isRemoteVideoDisabled]; + [cell setVideoDisabled: (_isAudioOnly) ? YES : peerConnection.isRemoteVideoDisabled]; return cell; } @@ -430,9 +432,11 @@ typedef NS_ENUM(NSInteger, CallState) { [cell setAudioDisabled:peer.isRemoteAudioDisabled]; }]; } else if ([message isEqualToString:@"videoOn"] || [message isEqualToString:@"videoOff"]) { - [self updatePeer:peer block:^(CallParticipantViewCell *cell) { - [cell setVideoDisabled:peer.isRemoteVideoDisabled]; - }]; + if (!_isAudioOnly) { + [self updatePeer:peer block:^(CallParticipantViewCell *cell) { + [cell setVideoDisabled:peer.isRemoteVideoDisabled]; + }]; + } } } - (void)callController:(NCCallController *)callController didReceiveNick:(NSString *)nick fromPeer:(NCPeerConnection *)peer diff --git a/VideoCalls/ContactsTableViewController.h b/VideoCalls/ContactsTableViewController.h index 556b7d88..0cc10dc3 100644 --- a/VideoCalls/ContactsTableViewController.h +++ b/VideoCalls/ContactsTableViewController.h @@ -8,6 +8,9 @@ #import +extern NSString * const NCSelectedContactForVoiceCallNotification; +extern NSString * const NCSelectedContactForVideoCallNotification; + @interface ContactsTableViewController : UITableViewController @end diff --git a/VideoCalls/ContactsTableViewController.m b/VideoCalls/ContactsTableViewController.m index e94ce798..932f3380 100644 --- a/VideoCalls/ContactsTableViewController.m +++ b/VideoCalls/ContactsTableViewController.m @@ -17,6 +17,9 @@ #import "UIImageView+Letters.h" #import "UIImageView+AFNetworking.h" +NSString * const NCSelectedContactForVoiceCallNotification = @"NCSelectedContactForVoiceCallNotification"; +NSString * const NCSelectedContactForVideoCallNotification = @"NCSelectedContactForVideoCallNotification"; + @interface ContactsTableViewController () { NSMutableArray *_contacts; @@ -162,6 +165,62 @@ }]; } +- (void)presentJoinCallOptionsForContactAtIndexPath:(NSIndexPath *)indexPath +{ + NCUser *contact = [_contacts objectAtIndex:indexPath.row]; + if (_searchController.active) { + contact = [_resultTableViewController.filteredContacts objectAtIndex:indexPath.row]; + } + + UIAlertController *optionsActionSheet = + [UIAlertController alertControllerWithTitle:contact.name + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + + [optionsActionSheet addAction:[UIAlertAction actionWithTitle:@"Call" + style:UIAlertActionStyleDefault + handler:^void (UIAlertAction *action) { + [self createCallWithContact:contact audioOnly:YES]; + }]]; + + [optionsActionSheet addAction:[UIAlertAction actionWithTitle:@"Videocall" + style:UIAlertActionStyleDefault + handler:^void (UIAlertAction *action) { + [self createCallWithContact:contact audioOnly:NO]; + }]]; + + [optionsActionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + + // Presentation on iPads + optionsActionSheet.popoverPresentationController.sourceView = self.tableView; + optionsActionSheet.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath]; + + [self presentViewController:optionsActionSheet animated:YES completion:nil]; +} + +- (void)createCallWithContact:(NCUser *)contact audioOnly:(BOOL)audioOnly +{ + [[NCAPIController sharedInstance] createRoomWith:contact.userId + ofType:kNCRoomTypeOneToOneCall + andName:nil + withCompletionBlock:^(NSString *token, NSError *error) { + if (!error) { + NSLog(@"Room %@ with %@ created", token, contact.name); + if (audioOnly) { + [[NSNotificationCenter defaultCenter] postNotificationName:NCSelectedContactForVoiceCallNotification + object:self + userInfo:@{@"token":token}]; + } else { + [[NSNotificationCenter defaultCenter] postNotificationName:NCSelectedContactForVideoCallNotification + object:self + userInfo:@{@"token":token}]; + } + } else { + NSLog(@"Failed creating a room with %@", contact.name); + } + }]; +} + #pragma mark - Search controller - (void)updateSearchResultsForSearchController:(UISearchController *)searchController @@ -213,25 +272,7 @@ if ([NCConnectionController sharedInstance].connectionState == kConnectionStateDisconnected) { [[NCUserInterfaceController sharedInstance] presentOfflineWarningAlert]; } else { - NCUser *contact = [_contacts objectAtIndex:indexPath.row]; - if (_searchController.active) { - contact = [_resultTableViewController.filteredContacts objectAtIndex:indexPath.row]; - } - - [[NCAPIController sharedInstance] createRoomWith:contact.userId - ofType:kNCRoomTypeOneToOneCall - andName:nil - withCompletionBlock:^(NSString *token, NSError *error) { - if (!error) { - // Join created room. - NSLog(@"Room %@ with %@ created", token, contact.name); - [[NSNotificationCenter defaultCenter] postNotificationName:NCRoomCreatedNotification - object:self - userInfo:@{@"token":token}]; - } else { - NSLog(@"Failed creating a room with %@", contact.name); - } - }]; + [self presentJoinCallOptionsForContactAtIndexPath:indexPath]; } [tableView deselectRowAtIndexPath:indexPath animated:YES]; diff --git a/VideoCalls/NCAPIController.h b/VideoCalls/NCAPIController.h index af2febe0..c19c9ceb 100644 --- a/VideoCalls/NCAPIController.h +++ b/VideoCalls/NCAPIController.h @@ -45,8 +45,6 @@ typedef void (^UnsubscribeToNextcloudServerCompletionBlock)(NSError *error); typedef void (^SubscribeToPushProxyCompletionBlock)(NSError *error); typedef void (^UnsubscribeToPushProxyCompletionBlock)(NSError *error); -extern NSString * const NCRoomCreatedNotification; - @interface NCAPIController : NSObject diff --git a/VideoCalls/NCAPIController.m b/VideoCalls/NCAPIController.m index f442b15d..2a169272 100644 --- a/VideoCalls/NCAPIController.m +++ b/VideoCalls/NCAPIController.m @@ -15,8 +15,6 @@ NSString * const kNCOCSAPIVersion = @"/ocs/v2.php"; NSString * const kNCSpreedAPIVersion = @"/apps/spreed/api/v1"; -NSString * const NCRoomCreatedNotification = @"NCRoomCreatedNotification"; - @interface NCAPIController () { NSString *_serverUrl; diff --git a/VideoCalls/NCCallController.h b/VideoCalls/NCCallController.h index db2952bd..da47c3b3 100644 --- a/VideoCalls/NCCallController.h +++ b/VideoCalls/NCCallController.h @@ -44,7 +44,7 @@ typedef void (^GetUserIdForSessionIdCompletionBlock)(NSString *userId, NSError * @property (nonatomic, strong) NSMutableArray *renderers; -- (instancetype)initWithDelegate:(id)delegate; +- (instancetype)initWithDelegate:(id)delegate forAudioOnlyCall:(BOOL)audioOnly; - (void)startCall; - (void)leaveCall; - (void)toggleCamera; diff --git a/VideoCalls/NCCallController.m b/VideoCalls/NCCallController.m index 12ee84ea..4d997406 100644 --- a/VideoCalls/NCCallController.m +++ b/VideoCalls/NCCallController.m @@ -29,6 +29,7 @@ static NSString * const kNCVideoTrackKind = @"video"; @interface NCCallController () +@property (nonatomic, assign) BOOL isAudioOnly; @property (nonatomic, assign) BOOL leavingCall; @property (nonatomic, strong) NSTimer *pingTimer; @property (nonatomic, strong) AVAudioRecorder *recorder; @@ -46,12 +47,13 @@ static NSString * const kNCVideoTrackKind = @"video"; @implementation NCCallController -- (instancetype)initWithDelegate:(id)delegate +- (instancetype)initWithDelegate:(id)delegate forAudioOnlyCall:(BOOL)audioOnly { self = [super init]; if (self) { _delegate = delegate; + _isAudioOnly = audioOnly; _peerConnectionFactory = [[RTCPeerConnectionFactory alloc] init]; _connectionsDict = [[NSMutableDictionary alloc] init]; _usersInRoom = [[NSArray alloc] init]; @@ -285,7 +287,9 @@ static NSString * const kNCVideoTrackKind = @"video"; RTCMediaStream *localMediaStream = [_peerConnectionFactory mediaStreamWithStreamId:kNCMediaStreamId]; self.localStream = localMediaStream; [self createLocalAudioTrack]; - [self createLocalVideoTrack]; + if (!_isAudioOnly) { + [self createLocalVideoTrack]; + } } #pragma mark - Audio session configuration @@ -334,7 +338,7 @@ static NSString * const kNCVideoTrackKind = @"video"; NSLog(@"Creating a peer for %@", sessionId); NSArray *iceServers = [_signalingController getIceServers]; - peerConnectionWrapper = [[NCPeerConnection alloc] initWithSessionId:sessionId andICEServers:iceServers]; + peerConnectionWrapper = [[NCPeerConnection alloc] initWithSessionId:sessionId andICEServers:iceServers forAudioOnlyCall:_isAudioOnly]; peerConnectionWrapper.delegate = self; // TODO: Try to get display name here [peerConnectionWrapper.peerConnection addStream:_localStream]; @@ -542,7 +546,7 @@ static NSString * const kNCVideoTrackKind = @"video"; } // Send current video state - if (self.isVideoEnabled) { + if (self.isVideoEnabled && !_isAudioOnly) { NSLog(@"Send videoOn"); [peerConnection sendDataChannelMessageOfType:@"videoOn" withPayload:nil]; } else { diff --git a/VideoCalls/NCPeerConnection.h b/VideoCalls/NCPeerConnection.h index 0397f4e6..514c34ab 100644 --- a/VideoCalls/NCPeerConnection.h +++ b/VideoCalls/NCPeerConnection.h @@ -46,6 +46,7 @@ @property (nonatomic, copy) NSString *peerId; @property (nonatomic, copy) NSString *peerName; +@property (nonatomic, assign) BOOL isAudioOnly; @property (nonatomic, strong) RTCPeerConnection *peerConnection; @property (nonatomic, strong) RTCDataChannel *localDataChannel; @property (nonatomic, strong) RTCDataChannel *remoteDataChannel; @@ -54,7 +55,7 @@ @property (nonatomic, strong, readonly) NSMutableArray *queuedRemoteCandidates; @property (nonatomic, strong) RTCMediaStream *remoteStream; -- (instancetype)initWithSessionId:(NSString *)sessionId andICEServers:(NSArray *)iceServers; +- (instancetype)initWithSessionId:(NSString *)sessionId andICEServers:(NSArray *)iceServers forAudioOnlyCall:(BOOL)audioOnly; - (void)addICECandidate:(RTCIceCandidate *)candidate; - (void)setRemoteDescription:(RTCSessionDescription *)sessionDescription; - (void)sendOffer; diff --git a/VideoCalls/NCPeerConnection.m b/VideoCalls/NCPeerConnection.m index 5e3a9c35..f33b745c 100644 --- a/VideoCalls/NCPeerConnection.m +++ b/VideoCalls/NCPeerConnection.m @@ -27,7 +27,7 @@ @implementation NCPeerConnection -- (instancetype)initWithSessionId:(NSString *)sessionId andICEServers:(NSArray *)iceServers +- (instancetype)initWithSessionId:(NSString *)sessionId andICEServers:(NSArray *)iceServers forAudioOnlyCall:(BOOL)audioOnly { self = [super init]; @@ -47,6 +47,7 @@ _peerConnection = peerConnection; _peerId = sessionId; + _isAudioOnly = audioOnly; } return self; @@ -376,6 +377,13 @@ @"OfferToReceiveVideo" : @"true" }; + if (_isAudioOnly) { + mandatoryConstraints = @{ + @"OfferToReceiveAudio" : @"true", + @"OfferToReceiveVideo" : @"false" + }; + } + NSDictionary *optionalConstraints = @{ @"internalSctpDataChannels": @"true", @"DtlsSrtpKeyAgreement": @"true" diff --git a/VideoCalls/NCPushNotification.h b/VideoCalls/NCPushNotification.h index a78b1045..a9025291 100644 --- a/VideoCalls/NCPushNotification.h +++ b/VideoCalls/NCPushNotification.h @@ -23,7 +23,8 @@ extern NSString * const kNCPNTypeCallKey; extern NSString * const kNCPNTypeRoomKey; extern NSString * const kNCPNTypeChatKey; -extern NSString * const NCPushNotificationJoinCallAcceptedNotification; +extern NSString * const NCPushNotificationJoinAudioCallAcceptedNotification; +extern NSString * const NCPushNotificationJoinVideoCallAcceptedNotification; @interface NCPushNotification : NSObject diff --git a/VideoCalls/NCPushNotification.m b/VideoCalls/NCPushNotification.m index a0100710..419bb093 100644 --- a/VideoCalls/NCPushNotification.m +++ b/VideoCalls/NCPushNotification.m @@ -19,7 +19,8 @@ NSString * const kNCPNTypeCallKey = @"call"; NSString * const kNCPNTypeRoomKey = @"room"; NSString * const kNCPNTypeChatKey = @"chat"; -NSString * const NCPushNotificationJoinCallAcceptedNotification = @"NCPushNotificationJoinCallAcceptedNotification"; +NSString * const NCPushNotificationJoinAudioCallAcceptedNotification = @"NCPushNotificationJoinAudioCallAcceptedNotification"; +NSString * const NCPushNotificationJoinVideoCallAcceptedNotification = @"NCPushNotificationJoinVideoCallAcceptedNotification"; + (instancetype)pushNotificationFromDecryptedString:(NSString *)decryptedString diff --git a/VideoCalls/NCUserInterfaceController.m b/VideoCalls/NCUserInterfaceController.m index e0e95157..064734fb 100644 --- a/VideoCalls/NCUserInterfaceController.m +++ b/VideoCalls/NCUserInterfaceController.m @@ -106,22 +106,33 @@ message:@"Do you want to join this call?" preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *joinButton = [UIAlertAction - actionWithTitle:@"Join call" - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * _Nonnull action) { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:pushNotification forKey:@"pushNotification"]; - [[NSNotificationCenter defaultCenter] postNotificationName:NCPushNotificationJoinCallAcceptedNotification - object:self - userInfo:userInfo]; - }]; + UIAlertAction *joinAudioButton = [UIAlertAction + actionWithTitle:@"Join call (audio only)" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:pushNotification forKey:@"pushNotification"]; + [[NSNotificationCenter defaultCenter] postNotificationName:NCPushNotificationJoinAudioCallAcceptedNotification + object:self + userInfo:userInfo]; + }]; + + UIAlertAction *joinVideoButton = [UIAlertAction + actionWithTitle:@"Join call with video" + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * _Nonnull action) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:pushNotification forKey:@"pushNotification"]; + [[NSNotificationCenter defaultCenter] postNotificationName:NCPushNotificationJoinVideoCallAcceptedNotification + object:self + userInfo:userInfo]; + }]; UIAlertAction* cancelButton = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]; - [alert addAction:joinButton]; + [alert addAction:joinAudioButton]; + [alert addAction:joinVideoButton]; [alert addAction:cancelButton]; // Do not show join call dialog until we don't handle 'hangup current call'/'join new one' properly. diff --git a/VideoCalls/RoomsTableViewController.m b/VideoCalls/RoomsTableViewController.m index cbf73715..4953f816 100644 --- a/VideoCalls/RoomsTableViewController.m +++ b/VideoCalls/RoomsTableViewController.m @@ -10,6 +10,7 @@ #import "AFNetworking.h" #import "CallViewController.h" +#import "ContactsTableViewController.h" #import "AddParticipantsTableViewController.h" #import "RoomTableViewCell.h" #import "CCCertificate.h" @@ -58,10 +59,12 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); self.tabBarController.tabBar.tintColor = [UIColor colorWithRed:0.00 green:0.51 blue:0.79 alpha:1.0]; //#0082C9 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(serverCapabilitiesReceived:) name:NCServerCapabilitiesReceivedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(joinCallAccepted:) name:NCPushNotificationJoinCallAcceptedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(joinAudioCallAccepted:) name:NCPushNotificationJoinAudioCallAcceptedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(joinVideoCallAccepted:) name:NCPushNotificationJoinVideoCallAcceptedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appStateHasChanged:) name:NCAppStateHasChangedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(connectionStateHasChanged:) name:NCConnectionStateHasChangedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(roomHasBeenCreated:) name:NCRoomCreatedNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userSelectedContactForVoiceCall:) name:NCSelectedContactForVoiceCallNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userSelectedContactForVideoCall:) name:NCSelectedContactForVideoCallNotification object:nil]; } - (void)dealloc @@ -95,10 +98,16 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); } } -- (void)joinCallAccepted:(NSNotification *)notification +- (void)joinAudioCallAccepted:(NSNotification *)notification { NCPushNotification *pushNotification = [notification.userInfo objectForKey:@"pushNotification"]; - [self joinCallWithCallId:pushNotification.pnId]; + [self joinCallWithCallId:pushNotification.pnId audioOnly:YES]; +} + +- (void)joinVideoCallAccepted:(NSNotification *)notification +{ + NCPushNotification *pushNotification = [notification.userInfo objectForKey:@"pushNotification"]; + [self joinCallWithCallId:pushNotification.pnId audioOnly:NO]; } - (void)appStateHasChanged:(NSNotification *)notification @@ -113,10 +122,16 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); [self adaptInterfaceForConnectionState:connectionState]; } -- (void)roomHasBeenCreated:(NSNotification *)notification +- (void)userSelectedContactForVoiceCall:(NSNotification *)notification { NSString *roomToken = [notification.userInfo objectForKey:@"token"]; - [self joinCallWithCallToken:roomToken]; + [self joinCallWithCallToken:roomToken audioOnly:YES]; +} + +- (void)userSelectedContactForVideoCall:(NSNotification *)notification +{ + NSString *roomToken = [notification.userInfo objectForKey:@"token"]; + [self joinCallWithCallToken:roomToken audioOnly:NO]; } #pragma mark - Interface Builder Actions @@ -477,6 +492,39 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); }]; } +- (void)presentJoinCallOptionsForRoomAtIndexPath:(NSIndexPath *)indexPath +{ + NCRoom *room = [_rooms objectAtIndex:indexPath.row]; + + UIAlertController *optionsActionSheet = + [UIAlertController alertControllerWithTitle:room.displayName + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + + UIAlertAction *callAction = [UIAlertAction actionWithTitle:@"Call" + style:UIAlertActionStyleDefault + handler:^void (UIAlertAction *action) { + [self startCallInRoom:room audioOnly:YES]; + }]; + + UIAlertAction *videocallAction = [UIAlertAction actionWithTitle:@"Videocall" + style:UIAlertActionStyleDefault + handler:^void (UIAlertAction *action) { + [self startCallInRoom:room audioOnly:NO]; + }]; + + [optionsActionSheet addAction:callAction]; + [optionsActionSheet addAction:videocallAction]; + + [optionsActionSheet addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]]; + + // Presentation on iPads + optionsActionSheet.popoverPresentationController.sourceView = self.tableView; + optionsActionSheet.popoverPresentationController.sourceRect = [self.tableView rectForRowAtIndexPath:indexPath]; + + [self presentViewController:optionsActionSheet animated:YES completion:nil]; +} + #pragma mark - Public Calls - (void)startRoomCreationFlowForPublicRoom:(BOOL)public @@ -550,37 +598,37 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); return room; } -- (void)startCallInRoom:(NCRoom *)room +- (void)startCallInRoom:(NCRoom *)room audioOnly:(BOOL)audioOnly { - CallViewController *callVC = [[CallViewController alloc] initCallInRoom:room asUser:[[NCSettingsController sharedInstance] ncUserDisplayName]]; + CallViewController *callVC = [[CallViewController alloc] initCallInRoom:room asUser:[[NCSettingsController sharedInstance] ncUserDisplayName] audioOnly:audioOnly]; [[NCUserInterfaceController sharedInstance] presentCallViewController:callVC]; } -- (void)joinCallWithCallId:(NSInteger)callId +- (void)joinCallWithCallId:(NSInteger)callId audioOnly:(BOOL)audioOnly { NCRoom *room = [self getRoomForId:callId]; if (room) { - [self startCallInRoom:room]; + [self startCallInRoom:room audioOnly:audioOnly]; } else { //TODO: Show spinner? [[NCAPIController sharedInstance] getRoomWithId:callId withCompletionBlock:^(NCRoom *room, NSError *error) { if (!error) { - [self startCallInRoom:room]; + [self startCallInRoom:room audioOnly:audioOnly]; } }]; } } -- (void)joinCallWithCallToken:(NSString *)token +- (void)joinCallWithCallToken:(NSString *)token audioOnly:(BOOL)audioOnly { NCRoom *room = [self getRoomForToken:token]; if (room) { - [self startCallInRoom:room]; + [self startCallInRoom:room audioOnly:audioOnly]; } else { //TODO: Show spinner? [[NCAPIController sharedInstance] getRoomWithToken:token withCompletionBlock:^(NCRoom *room, NSError *error) { if (!error) { - [self startCallInRoom:room]; + [self startCallInRoom:room audioOnly:audioOnly]; } }]; } @@ -783,8 +831,7 @@ typedef void (^FetchRoomsCompletionBlock)(BOOL success); if ([NCConnectionController sharedInstance].connectionState == kConnectionStateDisconnected) { [[NCUserInterfaceController sharedInstance] presentOfflineWarningAlert]; } else { - NCRoom *room = [_rooms objectAtIndex:indexPath.row]; - [self startCallInRoom:room]; + [self presentJoinCallOptionsForRoomAtIndexPath:indexPath]; } [tableView deselectRowAtIndexPath:indexPath animated:YES]; }