From 883719f5672cc8dea294b18c79d71e67137a040d Mon Sep 17 00:00:00 2001 From: Alexandre Lision <alexandre.lision@savoirfairelinux.com> Date: Thu, 22 Oct 2015 17:37:45 -0400 Subject: [PATCH] call: add transfer ability This commit adds attended/unattended transfer capability It also improves call controls visibility Tuleap: #56 Change-Id: I66c2bc22f015f12dc58cf98768b8b3c689e6fdcb --- CMakeLists.txt | 8 +- data/dark/ic_action_transfer.png | Bin 0 -> 460 bytes src/BrokerVC.h | 31 ++++ src/BrokerVC.mm | 235 +++++++++++++++++++++++++++++++ src/CurrentCallVC.mm | 89 ++++++++---- ui/Base.lproj/Broker.xib | 134 ++++++++++++++++++ ui/Base.lproj/CurrentCall.xib | 159 +++++++++++++-------- 7 files changed, 567 insertions(+), 89 deletions(-) create mode 100644 data/dark/ic_action_transfer.png create mode 100644 src/BrokerVC.h create mode 100644 src/BrokerVC.mm create mode 100644 ui/Base.lproj/Broker.xib diff --git a/CMakeLists.txt b/CMakeLists.txt index 00470ad8..9b44305a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,7 +111,9 @@ SET(ringclient_CONTROLLERS src/PersonLinkerVC.mm src/PersonLinkerVC.h src/SmartViewVC.mm - src/SmartViewVC.h) + src/SmartViewVC.h + src/BrokerVC.mm + src/BrokerVC.h) SET(ringclient_BACKENDS src/backends/AddressBookBackend.mm @@ -160,7 +162,8 @@ SET(ringclient_XIBS PreferencesWindow RingWizard CertificateWindow - PersonLinker) + PersonLinker + Broker) # Icons # This part tells CMake where to find and install the file itself @@ -186,6 +189,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_record.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_call_received.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_call_missed.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_call_made.png +${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_transfer.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ancrage.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/audio.png ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_person_add.png diff --git a/data/dark/ic_action_transfer.png b/data/dark/ic_action_transfer.png new file mode 100644 index 0000000000000000000000000000000000000000..a84953a7d3a053897fbdb46cbe605602e6d814e5 GIT binary patch literal 460 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BPWE(h45?szJHxk2Dp17j zyw4ryU0!p$g#JW!FZiP5<mCPR1h0wiJI5m_%w4-X?YTR=bON<Z_lWdY?A+t1@V&<P z{`Ut7AKAWtihpR)_t=8>-i?9>Q7Px!!n0n?6zTMsD}U#t_s-2Kp|3>#R(PGCbCUD< z5s&4<{+T}i6yim#E>4+uQdDwPiIT=u%hfG?DqM3pyzZZLt^4fP?ln<QK4wBX_tw7H zPPR{}f0uMFIm-9*QPA4H*q6LN-<xP&Ruk^s7<PQ!7QyTHISoa7x5gb`RU$Cmy5&XZ zv9R^Yp}V?Pi#mn4DqnsbG4;vOAF`r)Pn;mAEapTj7@6tbP!m?2R+*(=_f}|;{G7Xs zw0sX;)|GFW(Rqx^_Snonp>tv~0-tT3^S{!uvo<^Mv7TS~7H_Lhlka&1B;S9nliJK3 zTouy&W#+__#?M}C%-`o>IZ^vlx4*=OH*D@&3mMtg+`gR8U%D^h(7t%NqCcmPOC=oJ z*XSR?vhA<=GaJE)o`SZT$=7mDcI8BVbUL)Z`!Og8&&l7?dD+^~yKFWC0|SGntDnm{ Hr-UW|xp30v literal 0 HcmV?d00001 diff --git a/src/BrokerVC.h b/src/BrokerVC.h new file mode 100644 index 00000000..9e6190fe --- /dev/null +++ b/src/BrokerVC.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 Savoir-faire Linux Inc. + * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import <Cocoa/Cocoa.h> + +@interface BrokerVC : NSViewController + +enum class BrokerMode { + TRANSFER = 0, + //CONFERENCE +}; + +- (instancetype)initWithMode:(BrokerMode) m; + +@end diff --git a/src/BrokerVC.mm b/src/BrokerVC.mm new file mode 100644 index 00000000..bb374c9b --- /dev/null +++ b/src/BrokerVC.mm @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2015 Savoir-faire Linux Inc. + * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#import "BrokerVC.h" + +#import <QSortFilterProxyModel> +#import <QItemSelectionModel> +#import <QtMacExtras/qmacfunctions.h> +#import <QPixmap> + +//LRC +#import <recentmodel.h> +#import <callmodel.h> +#import <call.h> +#import <person.h> +#import <globalinstances.h> +#import <contactmethod.h> +#import <phonedirectorymodel.h> + +#import "QNSTreeController.h" +#import "delegates/ImageManipulationDelegate.h" + +// Display all items from peopleproxy() except current call +class NotCurrentItemModel : public QSortFilterProxyModel +{ +public: + NotCurrentItemModel(QSortFilterProxyModel* parent) : QSortFilterProxyModel(parent) + { + setSourceModel(parent); + } + + virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const + { + auto originIdx = ((QSortFilterProxyModel*)sourceModel())->mapToSource(sourceModel()->index(source_row,0,source_parent)); + auto c = RecentModel::instance().getActiveCall(originIdx); + + return (!c || (c && (c->state() != Call::State::CURRENT))) && + QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); + } +}; +@interface BrokerVC () + +@property BrokerMode mode; +@property (unsafe_unretained) IBOutlet NSOutlineView *smartView; +@property (strong) QNSTreeController *treeController; +@property QSortFilterProxyModel* recentFilterModel; + +@end + +@implementation BrokerVC + +// Tags for views +NSInteger const IMAGE_TAG = 100; +NSInteger const DISPLAYNAME_TAG = 200; +NSInteger const DETAILS_TAG = 300; +NSInteger const CALL_BUTTON_TAG = 400; +NSInteger const TXT_BUTTON_TAG = 500; + +- (instancetype)initWithMode:(BrokerMode)m { + self = [super init]; + if (self) { + [self setMode:m]; + } + return self; +} + +- (NSString *)nibName +{ + return @"Broker"; +} + +- (void)dealloc +{ + delete _recentFilterModel; +} + +- (void)loadView +{ + [super loadView]; + _recentFilterModel = new NotCurrentItemModel(RecentModel::instance().peopleProxy()); + _treeController = [[QNSTreeController alloc] initWithQModel:_recentFilterModel]; + + [_treeController setAvoidsEmptySelection:NO]; + [_treeController setChildrenKeyPath:@"children"]; + + [_smartView bind:@"content" toObject:_treeController withKeyPath:@"arrangedObjects" options:nil]; + [_smartView bind:@"sortDescriptors" toObject:_treeController withKeyPath:@"sortDescriptors" options:nil]; + [_smartView bind:@"selectionIndexPaths" toObject:_treeController withKeyPath:@"selectionIndexPaths" options:nil]; + [_smartView setTarget:self]; + [_smartView setDoubleAction:@selector(placeTransfer:)]; +} + +// ------------------------------------------------------------------------------- +// transfer on click on Person or ContactMethod +// ------------------------------------------------------------------------------- +- (void)placeTransfer:(id)sender +{ + auto current = CallModel::instance().selectedCall(); + + if (!current || [_treeController selectedNodes].count == 0) + return; + + QModelIndex qIdx = [_treeController toQIdx:[_treeController selectedNodes][0]]; + auto originIdx = RecentModel::instance().peopleProxy()->mapToSource(_recentFilterModel->mapToSource(qIdx)); + + auto transfer = RecentModel::instance().getActiveCall(originIdx); + if (transfer) { //realise an attended transfer between the two calls + CallModel::instance().attendedTransfer(current, transfer); + return; + } + + ContactMethod* m = nil; + auto contactmethods = RecentModel::instance().getContactMethods(originIdx); + if (contactmethods.size() > 0) { // Before calling check if we properly extracted at least one contact method + m = contactmethods.first(); + CallModel::instance().transfer(current, m); + } +} + +// ------------------------------------------------------------------------------- +// transfer to unknown URI +// ------------------------------------------------------------------------------- +- (void) transferTo:(NSString*) uri +{ + auto current = CallModel::instance().selectedCall(); + if (!current) + return; + auto number = PhoneDirectoryModel::instance().getNumber(QString::fromNSString(uri)); + CallModel::instance().transfer(current, number); +} + +#pragma mark - NSOutlineViewDelegate methods + +// ------------------------------------------------------------------------------- +// shouldSelectItem:item +// ------------------------------------------------------------------------------- +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item; +{ + return YES; +} + +// ------------------------------------------------------------------------------- +// shouldEditTableColumn:tableColumn:item +// +// Decide to allow the edit of the given outline view "item". +// ------------------------------------------------------------------------------- +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + return NO; +} + +// ------------------------------------------------------------------------------- +// View Based OutlineView: See the delegate method -tableView:viewForTableColumn:row: in NSTableView. +// ------------------------------------------------------------------------------- +- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + auto qIdx = [_treeController toQIdx:((NSTreeNode*)item)]; + NSTableCellView *result; + + if (!qIdx.parent().isValid()) { + result = [outlineView makeViewWithIdentifier:@"MainCell" owner:outlineView]; + } else { + result = [outlineView makeViewWithIdentifier:@"CallCell" owner:outlineView]; + } + + auto finalIdx = RecentModel::instance().peopleProxy()->mapToSource(_recentFilterModel->mapToSource(qIdx)); + + NSTextField* details = [result viewWithTag:DETAILS_TAG]; + if (auto call = RecentModel::instance().getActiveCall(finalIdx)) { + [details setStringValue:call->roleData((int)Ring::Role::FormattedState).toString().toNSString()]; + } else { + [details setStringValue:qIdx.data((int)Ring::Role::FormattedLastUsed).toString().toNSString()]; + } + NSTextField* displayName = [result viewWithTag:DISPLAYNAME_TAG]; + [displayName setStringValue:qIdx.data(Qt::DisplayRole).toString().toNSString()]; + NSImageView* photoView = [result viewWithTag:IMAGE_TAG]; + Person* p = qvariant_cast<Person*>(qIdx.data((int)Person::Role::Object)); + QVariant photo = GlobalInstances::pixmapManipulator().contactPhoto(p, QSize(40,40)); + [photoView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))]; + return result; +} + +// ------------------------------------------------------------------------------- +// View Based OutlineView: See the delegate method -tableView:rowViewForRow: in NSTableView. +// ------------------------------------------------------------------------------- +- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item +{ + return [outlineView makeViewWithIdentifier:@"HoverRowView" owner:nil]; +} + +- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item +{ + QModelIndex qIdx = [_treeController toQIdx:((NSTreeNode*)item)]; + return (((NSTreeNode*)item).indexPath.length == 1) ? 60.0 : 45.0; +} + +#pragma mark - NSTextFieldDelegate + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector +{ + if (commandSelector == @selector(insertNewline:)) { + if([fieldEditor.textStorage.string isNotEqualTo:@""]) { + [self transferTo:fieldEditor.textStorage.string]; + return YES; + } + } + + return NO; +} + +- (void)controlTextDidChange:(NSNotification *) notification +{ + NSTextView *textView = notification.userInfo[@"NSFieldEditor"]; + _recentFilterModel->setFilterRegExp(QRegExp(QString::fromNSString(textView.textStorage.string), Qt::CaseInsensitive, QRegExp::FixedString)); + [_smartView scrollToBeginningOfDocument:nil]; +} + + +@end diff --git a/src/CurrentCallVC.mm b/src/CurrentCallVC.mm index b6dc35e1..30659003 100644 --- a/src/CurrentCallVC.mm +++ b/src/CurrentCallVC.mm @@ -36,6 +36,7 @@ #import "views/CallView.h" #import "PersonLinkerVC.h" #import "ChatVC.h" +#import "BrokerVC.h" @interface RendererConnectionsHolder : NSObject @@ -51,28 +52,30 @@ @interface CurrentCallVC () <NSPopoverDelegate, ContactLinkedDelegate> -@property (unsafe_unretained) IBOutlet NSTextField *personLabel; -@property (unsafe_unretained) IBOutlet NSTextField *stateLabel; -@property (unsafe_unretained) IBOutlet NSButton *holdOnOffButton; -@property (unsafe_unretained) IBOutlet NSButton *hangUpButton; -@property (unsafe_unretained) IBOutlet NSButton *recordOnOffButton; -@property (unsafe_unretained) IBOutlet NSButton *pickUpButton; -@property (unsafe_unretained) IBOutlet NSButton *muteAudioButton; -@property (unsafe_unretained) IBOutlet NSButton *muteVideoButton; -@property (unsafe_unretained) IBOutlet NSButton *addContactButton; -@property (unsafe_unretained) IBOutlet NSView *headerContainer; -@property (unsafe_unretained) IBOutlet NSButton *qualityButton; +@property (unsafe_unretained) IBOutlet NSTextField* personLabel; +@property (unsafe_unretained) IBOutlet NSTextField* stateLabel; +@property (unsafe_unretained) IBOutlet NSButton* holdOnOffButton; +@property (unsafe_unretained) IBOutlet NSButton* hangUpButton; +@property (unsafe_unretained) IBOutlet NSButton* recordOnOffButton; +@property (unsafe_unretained) IBOutlet NSButton* pickUpButton; +@property (unsafe_unretained) IBOutlet NSButton* muteAudioButton; +@property (unsafe_unretained) IBOutlet NSButton* muteVideoButton; +@property (unsafe_unretained) IBOutlet NSButton* addContactButton; +@property (unsafe_unretained) IBOutlet NSButton* qualityButton; +@property (unsafe_unretained) IBOutlet NSButton* transferButton; +@property (unsafe_unretained) IBOutlet NSView* headerContainer; @property (unsafe_unretained) IBOutlet ITProgressIndicator *loadingIndicator; -@property (unsafe_unretained) IBOutlet NSTextField *timeSpentLabel; -@property (unsafe_unretained) IBOutlet NSView *controlsPanel; -@property (unsafe_unretained) IBOutlet NSSplitView *splitView; -@property (unsafe_unretained) IBOutlet NSButton *chatButton; +@property (unsafe_unretained) IBOutlet NSTextField* timeSpentLabel; +@property (unsafe_unretained) IBOutlet NSView* controlsPanel; +@property (unsafe_unretained) IBOutlet NSSplitView* splitView; +@property (unsafe_unretained) IBOutlet NSButton* chatButton; -@property (strong) IBOutlet NSPopover *qualityPopOver; +@property (strong) IBOutlet NSPopover* qualityPopOver; @property (strong) NSPopover* addToContactPopover; -@property (strong) IBOutlet ChatVC *chatVC; +@property (strong) NSPopover* transferPopoverVC; +@property (strong) IBOutlet ChatVC* chatVC; @property QHash<int, NSButton*> actionHash; @@ -92,8 +95,9 @@ @implementation CurrentCallVC @synthesize personLabel, actionHash, stateLabel, holdOnOffButton, hangUpButton, - recordOnOffButton, pickUpButton, chatButton, timeSpentLabel, - muteVideoButton, muteAudioButton, controlsPanel, headerContainer, videoView, videoLayer, previewLayer, previewView, splitView, loadingIndicator; + recordOnOffButton, pickUpButton, chatButton, transferButton, timeSpentLabel, + muteVideoButton, muteAudioButton, controlsPanel, headerContainer, videoView, + videoLayer, previewLayer, previewView, splitView, loadingIndicator; @synthesize previewHolder; @synthesize videoHolder; @@ -188,6 +192,7 @@ actionHash[ (int)UserActionModel::Action::HANGUP] = hangUpButton; actionHash[ (int)UserActionModel::Action::MUTE_AUDIO] = muteAudioButton; actionHash[ (int)UserActionModel::Action::MUTE_VIDEO] = muteVideoButton; + actionHash[ (int)UserActionModel::Action::SERVER_TRANSFER] = transferButton; videoLayer = [CALayer layer]; [videoView setWantsLayer:YES]; @@ -456,6 +461,12 @@ QObject::disconnect(previewHolder.started); [videoView.layer setContents:nil]; [previewView.layer setContents:nil]; + + [self.transferPopoverVC performClose:self]; + [self.addToContactPopover performClose:self]; + [self.qualityPopOver performClose:self]; + [self.chatButton setState:NSOffState]; + [self collapseRightView]; } -(void) animateOut @@ -538,8 +549,6 @@ if (self.addToContactPopover != nullptr) { [self.addToContactPopover performClose:self]; self.addToContactPopover = NULL; - [self.addContactButton setState:NSOffState]; - } else if (!contactmethod->contact() || contactmethod->contact()->isPlaceHolder()) { auto* editorVC = [[PersonLinkerVC alloc] initWithNibName:@"PersonLinker" bundle:nil]; [editorVC setMethodToLink:contactmethod]; @@ -553,6 +562,8 @@ [self.addToContactPopover showRelativeToRect:sender.bounds ofView:sender preferredEdge:NSMaxXEdge]; } + + [videoView setCallDelegate:nil]; } - (IBAction)hangUp:(id)sender { @@ -597,22 +608,50 @@ - (IBAction)displayQualityPopUp:(id)sender { [self.qualityPopOver showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMaxXEdge]; + [videoView setCallDelegate:nil]; + +} + +- (IBAction)toggleTransferView:(id)sender { + if (self.transferPopoverVC != nullptr) { + [self.transferPopoverVC performClose:self]; + self.transferPopoverVC = NULL; + [self.transferButton setState:NSOffState]; + } else { + auto* transferVC = [[BrokerVC alloc] initWithMode:BrokerMode::TRANSFER]; + self.transferPopoverVC = [[NSPopover alloc] init]; + [self.transferPopoverVC setContentSize:transferVC.view.frame.size]; + [self.transferPopoverVC setContentViewController:transferVC]; + [self.transferPopoverVC setAnimates:YES]; + [self.transferPopoverVC setBehavior:NSPopoverBehaviorTransient]; + [self.transferPopoverVC setDelegate:self]; + [self.transferPopoverVC showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge]; + [videoView setCallDelegate:nil]; + } } #pragma mark - NSPopOverDelegate - (void)popoverWillClose:(NSNotification *)notification { + if (self.transferPopoverVC != nullptr) { + [self.transferPopoverVC performClose:self]; + self.transferPopoverVC = NULL; + } + + if (self.addToContactPopover != nullptr) { + [self.addToContactPopover performClose:self]; + self.addToContactPopover = NULL; + } + [self.qualityButton setState:NSOffState]; [self.addContactButton setState:NSOffState]; + [self.transferButton setState:NSOffState]; } - (void)popoverDidClose:(NSNotification *)notification { - if (self.addToContactPopover != nullptr) { - [self.addToContactPopover performClose:self]; - self.addToContactPopover = NULL; - } + [videoView setCallDelegate:self]; } #pragma mark - ContactLinkedDelegate diff --git a/ui/Base.lproj/Broker.xib b/ui/Base.lproj/Broker.xib new file mode 100644 index 00000000..7ec8a29f --- /dev/null +++ b/ui/Base.lproj/Broker.xib @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> + <dependencies> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="8191"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="BrokerVC"> + <connections> + <outlet property="smartView" destination="ged-Fo-NiW" id="zOq-oj-zdQ"/> + <outlet property="view" destination="Hz6-mo-xeY" id="GmP-OL-Nu1"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application" customClass="NSObject"/> + <customView id="Hz6-mo-xeY"> + <rect key="frame" x="0.0" y="0.0" width="290" height="438"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + <subviews> + <searchField wantsLayer="YES" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6Sk-jm-KTk"> + <rect key="frame" x="20" y="396" width="250" height="22"/> + <searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Search or enter number" usesSingleLineMode="YES" bezelStyle="round" id="5vh-ub-Dsq"> + <font key="font" metaFont="system"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" white="1" alpha="0.0" colorSpace="deviceWhite"/> + </searchFieldCell> + <connections> + <outlet property="delegate" destination="-2" id="Bs5-0w-IAt"/> + </connections> + </searchField> + <scrollView fixedFrame="YES" borderType="none" autohidesScrollers="YES" horizontalLineScroll="62" horizontalPageScroll="10" verticalLineScroll="62" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A5E-AF-qKC"> + <rect key="frame" x="20" y="20" width="250" height="368"/> + <clipView key="contentView" ambiguous="YES" drawsBackground="NO" copiesOnScroll="NO" id="0Vv-ik-q6g"> + <rect key="frame" x="0.0" y="0.0" width="250" height="368"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <outlineView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="60" rowSizeStyle="automatic" viewBased="YES" indentationPerLevel="16" outlineTableColumn="pqp-hy-d8y" id="ged-Fo-NiW"> + <rect key="frame" x="0.0" y="0.0" width="250" height="368"/> + <autoresizingMask key="autoresizingMask"/> + <size key="intercellSpacing" width="3" height="2"/> + <color key="backgroundColor" white="1" alpha="0.0" colorSpace="deviceWhite"/> + <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> + <tableColumns> + <tableColumn width="247" minWidth="40" maxWidth="1000" id="pqp-hy-d8y"> + <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/> + </tableHeaderCell> + <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="3lU-Go-v0h"> + <font key="font" metaFont="system"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> + <prototypeCellViews> + <tableCellView identifier="MainCell" id="YLQ-KL-wQ3" userLabel="MainCell" customClass="ContextualTableCellView"> + <rect key="frame" x="1" y="1" width="247" height="60"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" tag="200" translatesAutoresizingMaskIntoConstraints="NO" id="bsM-kY-9k6"> + <rect key="frame" x="57" y="31" width="189" height="23"/> + <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Display Role" id="1Rl-Yq-z7r"> + <font key="font" size="16" name="HelveticaNeue-Light"/> + <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> + <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" tag="100" translatesAutoresizingMaskIntoConstraints="NO" id="RkA-HO-2Ad"> + <rect key="frame" x="3" y="6" width="48" height="48"/> + <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSUser" id="mZk-we-i9v"/> + </imageView> + <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="300" translatesAutoresizingMaskIntoConstraints="NO" id="eaV-2E-ENh"> + <rect key="frame" x="57" y="10" width="189" height="20"/> + <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="details" id="sQW-4V-hwv"> + <font key="font" size="13" name="HelveticaNeue-Light"/> + <color key="textColor" red="0.0" green="0.23137254901960785" blue="0.30588235294117649" alpha="1" colorSpace="calibratedRGB"/> + <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + </textField> + <button hidden="YES" verticalHuggingPriority="750" misplaced="YES" tag="400" translatesAutoresizingMaskIntoConstraints="NO" id="neN-xV-wb5" userLabel="Call Button" customClass="IconButton"> + <rect key="frame" x="288" y="18" width="25" height="25"/> + <constraints> + <constraint firstAttribute="width" constant="25" id="3a4-Cj-CU8"/> + <constraint firstAttribute="height" constant="25" id="8L3-91-Rn2"/> + </constraints> + <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_call" imagePosition="overlaps" alignment="center" allowsMixedState="YES" transparent="YES" imageScaling="proportionallyDown" inset="2" id="c4F-rE-v5i"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <connections> + <action selector="callClickedAtRow:" target="-1" id="hyg-jg-asa"/> + </connections> + </button> + </subviews> + <constraints> + <constraint firstAttribute="trailing" secondItem="neN-xV-wb5" secondAttribute="trailing" constant="8" id="MvK-3g-Jh7"/> + <constraint firstItem="neN-xV-wb5" firstAttribute="centerY" secondItem="YLQ-KL-wQ3" secondAttribute="centerY" constant="-0.5" id="T4T-wG-JiS"/> + </constraints> + <connections> + <outlet property="textField" destination="bsM-kY-9k6" id="XaM-Ih-4di"/> + </connections> + </tableCellView> + <customView identifier="HoverRowView" id="gbf-Fl-RiK" customClass="HoverTableRowView"> + <rect key="frame" x="1" y="63" width="247" height="55"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + </customView> + </prototypeCellViews> + </tableColumn> + </tableColumns> + <connections> + <outlet property="delegate" destination="-2" id="aSl-td-KL2"/> + </connections> + </outlineView> + </subviews> + <color key="backgroundColor" white="1" alpha="0.0" colorSpace="deviceWhite"/> + </clipView> + <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="Maf-69-awc"> + <rect key="frame" x="0.0" y="-16" width="0.0" height="16"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="fYr-Sf-2LL"> + <rect key="frame" x="-16" y="0.0" width="16" height="0.0"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + </scrollView> + </subviews> + <point key="canvasLocation" x="248" y="367"/> + </customView> + </objects> + <resources> + <image name="NSUser" width="32" height="32"/> + <image name="ic_action_call" width="72" height="72"/> + </resources> +</document> diff --git a/ui/Base.lproj/CurrentCall.xib b/ui/Base.lproj/CurrentCall.xib index 88373020..2c7966b8 100644 --- a/ui/Base.lproj/CurrentCall.xib +++ b/ui/Base.lproj/CurrentCall.xib @@ -25,6 +25,7 @@ <outlet property="splitView" destination="GIJ-gB-FZo" id="PM0-az-Q8X"/> <outlet property="stateLabel" destination="kFD-FB-vig" id="SSO-14-q2t"/> <outlet property="timeSpentLabel" destination="cIU-M7-xpN" id="9Rl-t3-gjY"/> + <outlet property="transferButton" destination="ChW-kg-Sja" id="v4D-c0-u6T"/> <outlet property="videoView" destination="2wf-Py-l6B" id="dEF-Gx-w6x"/> <outlet property="view" destination="Hz6-mo-xeY" id="VKn-lN-ijP"/> </connections> @@ -118,25 +119,11 @@ <constraint firstAttribute="centerY" secondItem="cIU-M7-xpN" secondAttribute="centerY" id="yvc-8B-cEu"/> </constraints> </customView> - <customView translatesAutoresizingMaskIntoConstraints="NO" id="6y6-RH-qOp" userLabel="Preview"> - <rect key="frame" x="480" y="20" width="175" height="120"/> - <constraints> - <constraint firstAttribute="height" constant="120" id="BvU-kV-0uD"/> - <constraint firstAttribute="width" constant="175" id="aEv-Tt-tSD"/> - </constraints> - </customView> - <customView translatesAutoresizingMaskIntoConstraints="NO" id="JwW-2h-DyZ" customClass="ITProgressIndicator"> - <rect key="frame" x="287" y="205" width="100" height="100"/> - <constraints> - <constraint firstAttribute="height" constant="100" id="gpl-re-hHE"/> - <constraint firstAttribute="width" constant="100" id="nmo-HF-lhL"/> - </constraints> - </customView> <customView translatesAutoresizingMaskIntoConstraints="NO" id="Eoi-B8-iL6" userLabel="Controls"> <rect key="frame" x="20" y="20" width="452" height="67"/> <subviews> <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tQl-cT-0Lb" userLabel="Mute Audio" customClass="IconButton"> - <rect key="frame" x="173" y="13" width="40" height="40"/> + <rect key="frame" x="158" y="13" width="40" height="40"/> <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_mute_audio" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="7wg-Q4-mbD"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> @@ -156,8 +143,12 @@ <action selector="muteAudio:" target="-2" id="DBk-mG-FLj"/> </connections> </button> - <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="qgD-3D-nD5" userLabel="Accept" customClass="IconButton"> - <rect key="frame" x="9" y="14" width="40" height="40"/> + <button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="qgD-3D-nD5" userLabel="Accept" customClass="IconButton"> + <rect key="frame" x="8" y="14" width="40" height="40"/> + <constraints> + <constraint firstAttribute="height" constant="40" id="IFG-ni-9mc"/> + <constraint firstAttribute="width" constant="40" id="uoL-Wy-Ek2"/> + </constraints> <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_call" imagePosition="overlaps" alignment="left" transparent="YES" imageScaling="proportionallyDown" id="CoO-HS-nEB"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> @@ -175,7 +166,7 @@ </connections> </button> <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oRa-pS-HN2" customClass="IconButton"> - <rect key="frame" x="340" y="13" width="40" height="40"/> + <rect key="frame" x="286" y="13" width="40" height="40"/> <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_record" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="rhz-4Z-avV"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" size="10" name=".HelveticaNeueDeskInterface-Regular"/> @@ -195,29 +186,8 @@ <action selector="toggleRecording:" target="-2" id="gAc-ZJ-9PN"/> </connections> </button> - <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="anb-Y8-JQi" userLabel="Hold" customClass="IconButton"> - <rect key="frame" x="129" y="14" width="40" height="40"/> - <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_hold" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="7w5-d1-mNe"> - <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> - </buttonCell> - <userDefinedRuntimeAttributes> - <userDefinedRuntimeAttribute type="number" keyPath="imageInsets"> - <integer key="value" value="8"/> - </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="color" keyPath="highlightColor"> - <color key="value" red="0.16862745100000001" green="0.70588235290000001" blue="0.78823529410000004" alpha="1" colorSpace="calibratedRGB"/> - </userDefinedRuntimeAttribute> - <userDefinedRuntimeAttribute type="color" keyPath="bgColor"> - <color key="value" red="0.16078431369999999" green="0.16078431369999999" blue="0.16078431369999999" alpha="0.80000000000000004" colorSpace="calibratedRGB"/> - </userDefinedRuntimeAttribute> - </userDefinedRuntimeAttributes> - <connections> - <action selector="toggleHold:" target="-2" id="O18-nN-hHE"/> - </connections> - </button> <button wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fmp-x4-Pef" userLabel="Chat" customClass="IconButton"> - <rect key="frame" x="404" y="12" width="40" height="40"/> + <rect key="frame" x="392" y="12" width="40" height="40"/> <backgroundFilters> <ciFilter name="CIColorMonochrome"> <configuration> @@ -247,7 +217,7 @@ </connections> </button> <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LVS-yZ-98V" userLabel="Mute Video" customClass="IconButton"> - <rect key="frame" x="223" y="13" width="40" height="40"/> + <rect key="frame" x="197" y="14" width="40" height="40"/> <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_mute_video" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="sSe-V6-C7i"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> @@ -267,18 +237,31 @@ <action selector="muteVideo:" target="-2" id="a6W-aB-zWX"/> </connections> </button> - <button wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="j52-5l-K3e" userLabel="Quality" customClass="IconButton"> - <rect key="frame" x="282" y="12" width="40" height="40"/> - <backgroundFilters> - <ciFilter name="CIColorMonochrome"> - <configuration> - <ciColor key="inputColor" red="1" green="0.53908979892730713" blue="0.15185309946537018" alpha="1"/> - <null key="inputImage"/> - <real key="inputIntensity" value="1"/> - </configuration> - </ciFilter> - </backgroundFilters> - <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_quality" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyUpOrDown" id="Vv0-lu-Pg9"> + <button horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Kjq-iM-NBL" userLabel="Hang Up" customClass="IconButton"> + <rect key="frame" x="58" y="13" width="40" height="40"/> + <constraints> + <constraint firstAttribute="width" constant="40" id="MYx-uE-Bej"/> + <constraint firstAttribute="height" constant="40" id="dmD-ga-Kwv"/> + </constraints> + <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_hangup" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="kR5-bV-2KY"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="color" keyPath="bgColor"> + <color key="value" red="0.94509803921568625" green="0.16078431372549018" blue="0.0" alpha="0.83999999999999997" colorSpace="calibratedRGB"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="number" keyPath="imageInsets"> + <integer key="value" value="8"/> + </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <action selector="hangUp:" target="-2" id="1Fj-b8-nfh"/> + </connections> + </button> + <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="anb-Y8-JQi" userLabel="Hold" customClass="IconButton"> + <rect key="frame" x="119" y="14" width="40" height="40"/> + <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_hold" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="7w5-d1-mNe"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> <font key="font" metaFont="system"/> </buttonCell> @@ -294,33 +277,84 @@ </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> <connections> - <action selector="displayQualityPopUp:" target="-2" id="EbO-ZD-Zsm"/> + <action selector="toggleHold:" target="-2" id="O18-nN-hHE"/> </connections> </button> - <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Kjq-iM-NBL" userLabel="Hang Up" customClass="IconButton"> - <rect key="frame" x="69" y="13" width="40" height="40"/> - <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_hangup" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="kR5-bV-2KY"> + <button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ChW-kg-Sja" customClass="IconButton"> + <rect key="frame" x="336" y="12" width="40" height="40"/> + <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_transfer" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyDown" id="FOs-Wt-c2R"> <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> - <font key="font" metaFont="system"/> + <font key="font" size="10" name=".HelveticaNeueDeskInterface-Regular"/> </buttonCell> <userDefinedRuntimeAttributes> + <userDefinedRuntimeAttribute type="number" keyPath="imageInsets"> + <integer key="value" value="8"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="color" keyPath="highlightColor"> + <color key="value" red="0.16862745100000001" green="0.70588235290000001" blue="0.78823529410000004" alpha="1" colorSpace="calibratedRGB"/> + </userDefinedRuntimeAttribute> <userDefinedRuntimeAttribute type="color" keyPath="bgColor"> - <color key="value" red="0.94509803921568625" green="0.16078431372549018" blue="0.0" alpha="0.83999999999999997" colorSpace="calibratedRGB"/> + <color key="value" red="0.16078431369999999" green="0.16078431369999999" blue="0.16078431369999999" alpha="0.80000000000000004" colorSpace="calibratedRGB"/> </userDefinedRuntimeAttribute> + </userDefinedRuntimeAttributes> + <connections> + <action selector="toggleTransferView:" target="-2" id="Gxt-lS-qZs"/> + </connections> + </button> + <button wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="j52-5l-K3e" userLabel="Quality" customClass="IconButton"> + <rect key="frame" x="242" y="14" width="40" height="40"/> + <backgroundFilters> + <ciFilter name="CIColorMonochrome"> + <configuration> + <ciColor key="inputColor" red="1" green="0.53908979892730713" blue="0.15185309946537018" alpha="1"/> + <null key="inputImage"/> + <real key="inputIntensity" value="1"/> + </configuration> + </ciFilter> + </backgroundFilters> + <buttonCell key="cell" type="square" bezelStyle="shadowlessSquare" image="ic_action_quality" imagePosition="overlaps" alignment="center" transparent="YES" imageScaling="proportionallyUpOrDown" id="Vv0-lu-Pg9"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + </buttonCell> + <userDefinedRuntimeAttributes> <userDefinedRuntimeAttribute type="number" keyPath="imageInsets"> <integer key="value" value="8"/> </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="color" keyPath="highlightColor"> + <color key="value" red="0.16862745100000001" green="0.70588235290000001" blue="0.78823529410000004" alpha="1" colorSpace="calibratedRGB"/> + </userDefinedRuntimeAttribute> + <userDefinedRuntimeAttribute type="color" keyPath="bgColor"> + <color key="value" red="0.16078431369999999" green="0.16078431369999999" blue="0.16078431369999999" alpha="0.80000000000000004" colorSpace="calibratedRGB"/> + </userDefinedRuntimeAttribute> </userDefinedRuntimeAttributes> <connections> - <action selector="hangUp:" target="-2" id="1Fj-b8-nfh"/> + <action selector="displayQualityPopUp:" target="-2" id="EbO-ZD-Zsm"/> </connections> </button> </subviews> <constraints> + <constraint firstItem="qgD-3D-nD5" firstAttribute="centerY" secondItem="Eoi-B8-iL6" secondAttribute="centerY" id="9NT-bT-9wJ"/> + <constraint firstItem="Kjq-iM-NBL" firstAttribute="centerY" secondItem="Eoi-B8-iL6" secondAttribute="centerY" id="FrX-Hd-30D"/> <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="385" id="TSJ-9A-brf"/> + <constraint firstItem="qgD-3D-nD5" firstAttribute="leading" secondItem="Eoi-B8-iL6" secondAttribute="leading" constant="8" id="hhR-YV-cu5"/> + <constraint firstItem="Kjq-iM-NBL" firstAttribute="leading" secondItem="qgD-3D-nD5" secondAttribute="trailing" constant="10" id="j0v-YO-8kM"/> <constraint firstAttribute="height" constant="67" id="ynu-O5-MN8"/> </constraints> </customView> + <customView misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="JwW-2h-DyZ" customClass="ITProgressIndicator"> + <rect key="frame" x="287" y="204" width="100" height="100"/> + <constraints> + <constraint firstAttribute="height" constant="100" id="gpl-re-hHE"/> + <constraint firstAttribute="width" constant="100" id="nmo-HF-lhL"/> + </constraints> + </customView> + <customView translatesAutoresizingMaskIntoConstraints="NO" id="6y6-RH-qOp" userLabel="Preview"> + <rect key="frame" x="480" y="20" width="175" height="120"/> + <constraints> + <constraint firstAttribute="height" constant="120" id="BvU-kV-0uD"/> + <constraint firstAttribute="width" constant="175" id="aEv-Tt-tSD"/> + </constraints> + </customView> </subviews> <constraints> <constraint firstAttribute="centerX" secondItem="JwW-2h-DyZ" secondAttribute="centerX" id="4eh-az-oI5"/> @@ -440,7 +474,7 @@ </connections> </viewController> <customView wantsLayer="YES" id="Y38-Id-LGC"> - <rect key="frame" x="0.0" y="4" width="56" height="161"/> + <rect key="frame" x="0.0" y="0.0" width="56" height="161"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6lf-Ut-Xbr"> @@ -481,7 +515,7 @@ </connections> </popover> <customView id="vW1-8R-ebu"> - <rect key="frame" x="-1" y="0.0" width="719" height="497"/> + <rect key="frame" x="0.0" y="0.0" width="719" height="497"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Pze-W9-iSO"> @@ -533,6 +567,7 @@ <image name="ic_action_mute_video" width="72" height="72"/> <image name="ic_action_quality" width="72" height="72"/> <image name="ic_action_record" width="54" height="54"/> + <image name="ic_action_transfer" width="72" height="72"/> <image name="ic_person_add" width="48" height="48"/> </resources> </document> -- GitLab