// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #import "OCTCallsViewController.h" #import "OCTSubmanagerCalls.h" #import "OCTManager.h" #import "OCTSubmanagerObjects.h" #import "OCTCall.h" #import "RLMCollectionChange+IndexSet.h" static NSString *const kCellIdent = @"cellIdent"; @interface OCTCallsViewController () @property (weak, nonatomic) id manager; @property (strong, nonatomic) RLMResults *calls; @property (strong, nonatomic) RLMNotificationToken *callsNotificationToken; @property (weak) IBOutlet NSTableView *callsTableView; @property (weak) IBOutlet NSView *videoContainerView; @property (strong, nonatomic) NSView *videoView; @end @implementation OCTCallsViewController - (instancetype)initWithManager:(id)manager { self = [super init]; if (! self) { return nil; } _manager = manager; [manager.calls setupAndReturnError:nil]; _calls = [manager.objects objectsForType:OCTFetchRequestTypeCall predicate:nil]; return self; } - (void)dealloc { [self.callsNotificationToken invalidate]; } - (void)viewDidLoad { [super viewDidLoad]; __weak typeof(self)weakSelf = self; self.callsNotificationToken = [self.calls addNotificationBlock:^(RLMResults *results, RLMCollectionChange *changes, NSError *error) { if (error) { NSLog(@"Failed to open Realm on background worker: %@", error); return; } NSTableView *tableView = weakSelf.callsTableView; // Initial run of the query will pass nil for the change information if (! changes) { [tableView reloadData]; return; } [tableView beginUpdates]; [tableView removeRowsAtIndexes:[changes deletionsSet] withAnimation:NSTableViewAnimationSlideLeft]; [tableView insertRowsAtIndexes:[changes insertionsSet] withAnimation:NSTableViewAnimationSlideRight]; [tableView reloadDataForRowIndexes:[changes modificationsSet] columnIndexes:[NSIndexSet indexSetWithIndex:0]]; [tableView endUpdates]; }]; } - (void)setupVideoView { if (self.videoView == self.manager.calls.videoFeed) { return; } if (self.videoView) { [self.videoView removeFromSuperview]; self.videoView = nil; } self.videoView = self.manager.calls.videoFeed; [self.videoContainerView addSubview:self.videoView]; NSLayoutConstraint *centerX = [NSLayoutConstraint constraintWithItem:self.videoView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.videoContainerView attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]; NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:self.videoView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.videoContainerView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:0.0]; NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:self.videoView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.videoContainerView attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]; NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:self.videoView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.videoContainerView attribute:NSLayoutAttributeHeight multiplier:1.0 constant:0.0]; self.videoView.translatesAutoresizingMaskIntoConstraints = NO; [self.videoView setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationVertical]; [self.videoView setContentHuggingPriority:NSLayoutPriorityDefaultLow forOrientation:NSLayoutConstraintOrientationHorizontal]; [self.videoContainerView addConstraints:@[centerX, centerY, widthConstraint, heightConstraint]]; } #pragma mark - NSTableViewDelegate - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return self.calls.count; } - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row { return 300.0; } - (void)tableViewSelectionDidChange:(NSNotification *)notification { [self doSomeThingWithCallWithBlock:^(OCTCall *call) { if (call.videoIsEnabled || call.friendSendingVideo) { [self setupVideoView]; } }]; } #pragma mark - NSTableViewDataSource - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { OCTCall *call = self.calls[row]; NSTextField *textField = [self.callsTableView makeViewWithIdentifier:kCellIdent owner:nil]; if (! textField) { textField = [NSTextField new]; textField.identifier = kCellIdent; } textField.stringValue = [NSString stringWithFormat:@"Friend name:%@\n" @"Call\n" @"Chat identifier %@\n" @"call status: %ld\n" @"callDuration: %f\n" @"friend sending audio: %d\n" @"friend receiving audio: %d\n" @"friend sending video: %d\n" @"friend receiving Video: %d\n", call.caller.name, call.chat.uniqueIdentifier, (long)call.status, call.callDuration, call.friendSendingAudio, call.friendAcceptingAudio, call.friendSendingVideo, call.friendAcceptingVideo]; ; return textField; } #pragma mark - Actions - (IBAction)callActionButtonPressed:(NSButton *)sender { [self doSomeThingWithCallWithBlock:^(OCTCall *call) { [self.manager.calls answerCall:call enableAudio:YES enableVideo:YES error:nil]; }]; } - (IBAction)sendCallControlSelected:(NSPopUpButton *)sender { [self doSomeThingWithCallWithBlock:^(OCTCall *call) { OCTToxAVCallControl control = (OCTToxAVCallControl)[sender indexOfSelectedItem]; [self.manager.calls sendCallControl:control toCall:call error:nil]; }]; } #pragma mark - Private - (OCTCall *)callForCurrentlySelectedRow { NSInteger selectedRow = self.callsTableView.selectedRow; if (selectedRow < 0) { return nil; } OCTCall *call = self.calls[selectedRow]; return call; } - (BOOL)doSomeThingWithCallWithBlock:(void (^)(OCTCall *))block { NSInteger selectedRow = self.callsTableView.selectedRow; if (selectedRow < 0) { return NO; } OCTCall *call = self.calls[selectedRow]; block(call); return YES; } @end