Rework new call view.

// FREEBIE
This commit is contained in:
Matthew Chen 2017-01-12 15:55:14 -05:00
parent 2119f33f81
commit 4a65a88512
14 changed files with 586 additions and 278 deletions

View File

@ -12,6 +12,7 @@ target 'Signal' do
pod 'SCWaveformView', '~> 1.0'
pod 'ZXingObjC'
pod 'JSQMessagesViewController'
pod 'PureLayout'
target 'SignalTests' do
inherit! :search_paths
end

View File

@ -40,6 +40,7 @@ PODS:
- PastelogKit (1.3):
- CocoaLumberjack (~> 2.0)
- ProtocolBuffers (1.9.11)
- PureLayout (3.0.2)
- Reachability (3.2)
- SAMKeychain (1.5.2)
- SCWaveformView (1.0.0)
@ -120,6 +121,7 @@ DEPENDENCIES:
- JSQMessagesViewController
- OpenSSL
- PastelogKit (~> 1.3)
- PureLayout
- SCWaveformView (~> 1.0)
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`, branch `mkirk/webrtc`)
- SocketRocket (from `https://github.com/facebook/SocketRocket.git`)
@ -159,6 +161,7 @@ SPEC CHECKSUMS:
OpenSSL: 246ffb948e9d56466727fd318134af35f5aa764e
PastelogKit: 7b475be4cf577713506a943dd940bcc0499c8bca
ProtocolBuffers: d509225eb2ea43d9582a59e94348fcf86e2abd65
PureLayout: 4d550abe49a94f24c2808b9b95db9131685fe4cd
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
SAMKeychain: 1865333198217411f35327e8da61b43de79b635b
SCWaveformView: 52a96750255d817e300565a80c81fb643e233e07
@ -170,6 +173,6 @@ SPEC CHECKSUMS:
YapDatabase: b1e43555a34a5298e23a045be96817a5ef0da58f
ZXingObjC: bf15b3814f7a105b6d99f47da2333c93a063650a
PODFILE CHECKSUM: 092dfd7f4709400f0b6afee7fb9667550e75ed7c
PODFILE CHECKSUM: 2ae77bac38b8d23b14175ac42d09dd8fce65bb5b
COCOAPODS: 1.0.1

View File

@ -7,9 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
0DD55B166906AF3368995978 /* libPods-Signal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 80CD5E19DD23200E7926EEA7 /* libPods-Signal.a */; };
30209C98DABCE82064B4EAF5 /* libPods-SignalTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A33D3C7EB4B17BDBD47F0FCC /* libPods-SignalTests.a */; };
341BB7491DB727EE001E2975 /* JSQMediaItem+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 341BB7481DB727EE001E2975 /* JSQMediaItem+OWS.m */; };
34535D821E256BE9008A4747 /* UIView+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = 34535D811E256BE9008A4747 /* UIView+OWS.m */; };
450873C31D9D5149006B54F2 /* OWSExpirationTimerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 450873C21D9D5149006B54F2 /* OWSExpirationTimerView.m */; };
450873C41D9D5149006B54F2 /* OWSExpirationTimerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 450873C21D9D5149006B54F2 /* OWSExpirationTimerView.m */; };
450873C71D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 450873C61D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m */; };
@ -112,6 +111,7 @@
45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */; };
45FBC5D21DF8592E00E9B410 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */; };
4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */; };
56EAA22E1901718F78C6DBB4 /* libPods-SignalTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1B5E7D6C9007F5E5761D79DD /* libPods-SignalTests.a */; };
701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; };
70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; };
7038632718F70C0700D4A43F /* CryptoTools.m in Sources */ = {isa = PBXBuildFile; fileRef = 7038632418F70C0700D4A43F /* CryptoTools.m */; };
@ -517,6 +517,7 @@
E197B62718BBF63B00F073E5 /* SoundBoard.m in Sources */ = {isa = PBXBuildFile; fileRef = E197B62618BBF63B00F073E5 /* SoundBoard.m */; };
E1CD329618BCFF9900B1A496 /* SoundInstance.m in Sources */ = {isa = PBXBuildFile; fileRef = E1CD329518BCFF9900B1A496 /* SoundInstance.m */; };
E94066151DFC5B7B00B15392 /* ContactsPicker.xib in Resources */ = {isa = PBXBuildFile; fileRef = E94066141DFC5B7B00B15392 /* ContactsPicker.xib */; };
E32B0699162419B7046BC643 /* libPods-Signal.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7DB8EE72F8522189E3E2CB45 /* libPods-Signal.a */; };
EF764C351DB67CC5000D9A87 /* UIViewController+CameraPermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = EF764C341DB67CC5000D9A87 /* UIViewController+CameraPermissions.m */; };
FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */; };
FC31962D1A06A2190094C78E /* FingerprintViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FC31962C1A06A2190094C78E /* FingerprintViewController.m */; };
@ -581,8 +582,11 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
1B5E7D6C9007F5E5761D79DD /* libPods-SignalTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SignalTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
341BB7471DB727EE001E2975 /* JSQMediaItem+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "JSQMediaItem+OWS.h"; sourceTree = "<group>"; };
341BB7481DB727EE001E2975 /* JSQMediaItem+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "JSQMediaItem+OWS.m"; sourceTree = "<group>"; };
34535D801E256BE9008A4747 /* UIView+OWS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+OWS.h"; sourceTree = "<group>"; };
34535D811E256BE9008A4747 /* UIView+OWS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+OWS.m"; sourceTree = "<group>"; };
450873C11D9D5149006B54F2 /* OWSExpirationTimerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSExpirationTimerView.h; sourceTree = "<group>"; };
450873C21D9D5149006B54F2 /* OWSExpirationTimerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSExpirationTimerView.m; sourceTree = "<group>"; };
450873C51D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSIncomingMessageCollectionViewCell.h; sourceTree = "<group>"; };
@ -899,14 +903,13 @@
76EB050C18170B33006006FC /* InCallViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InCallViewController.m; sourceTree = "<group>"; };
76EB052E18170B33006006FC /* ContactTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContactTableViewCell.h; sourceTree = "<group>"; };
76EB052F18170B33006006FC /* ContactTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContactTableViewCell.m; sourceTree = "<group>"; };
80CD5E19DD23200E7926EEA7 /* libPods-Signal.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Signal.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7DB8EE72F8522189E3E2CB45 /* libPods-Signal.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Signal.a"; sourceTree = BUILT_PRODUCTS_DIR; };
954AEE681DF33D32002E5410 /* ContactsPickerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContactsPickerTest.swift; sourceTree = "<group>"; };
A11CD70C17FA230600A2D1B1 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
A163E8AA16F3F6A90094D68B /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
A1C32D4D17A0652C000A904E /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; };
A1C32D4F17A06537000A904E /* AddressBookUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBookUI.framework; path = System/Library/Frameworks/AddressBookUI.framework; sourceTree = SDKROOT; };
A1FDCBEE16DAA6C300868894 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; };
A33D3C7EB4B17BDBD47F0FCC /* libPods-SignalTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SignalTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A507A3AF1A6C60E300BEED0D /* InboxTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = InboxTableViewCell.xib; path = "Signal/src/view controllers/InboxTableViewCell.xib"; sourceTree = SOURCE_ROOT; };
A5509EC91A69AB8B00ABA4BC /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Storyboard/Main.storyboard; sourceTree = "<group>"; };
A5509ECB1A69B1D600ABA4BC /* CountryCodeTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryCodeTableViewCell.h; sourceTree = "<group>"; };
@ -1241,7 +1244,7 @@
D221A090169C9E5E00537ABF /* Foundation.framework in Frameworks */,
D221A0E8169DFFC500537ABF /* AVFoundation.framework in Frameworks */,
D24B5BD5169F568C00681372 /* AudioToolbox.framework in Frameworks */,
0DD55B166906AF3368995978 /* libPods-Signal.a in Frameworks */,
E32B0699162419B7046BC643 /* libPods-Signal.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1264,7 +1267,7 @@
D202868116DBE0E7009068E9 /* CFNetwork.framework in Frameworks */,
D221A0AD169C9E5F00537ABF /* UIKit.framework in Frameworks */,
D221A0AE169C9E5F00537ABF /* Foundation.framework in Frameworks */,
30209C98DABCE82064B4EAF5 /* libPods-SignalTests.a in Frameworks */,
56EAA22E1901718F78C6DBB4 /* libPods-SignalTests.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -2404,8 +2407,8 @@
D221A08D169C9E5E00537ABF /* UIKit.framework */,
D221A08F169C9E5E00537ABF /* Foundation.framework */,
D221A091169C9E5E00537ABF /* CoreGraphics.framework */,
80CD5E19DD23200E7926EEA7 /* libPods-Signal.a */,
A33D3C7EB4B17BDBD47F0FCC /* libPods-SignalTests.a */,
7DB8EE72F8522189E3E2CB45 /* libPods-Signal.a */,
1B5E7D6C9007F5E5761D79DD /* libPods-SignalTests.a */,
);
name = Frameworks;
sourceTree = "<group>";
@ -2576,6 +2579,8 @@
FCFA64B61A24F6730007FB87 /* UIFont+OWS.m */,
B68112E81A4D9EC400BA82FF /* UIImage+normalizeImage.h */,
B68112E91A4D9EC400BA82FF /* UIImage+normalizeImage.m */,
34535D801E256BE9008A4747 /* UIView+OWS.h */,
34535D811E256BE9008A4747 /* UIView+OWS.m */,
EF764C331DB67CC5000D9A87 /* UIViewController+CameraPermissions.h */,
EF764C341DB67CC5000D9A87 /* UIViewController+CameraPermissions.m */,
);
@ -3117,6 +3122,7 @@
76EB05F018170B33006006FC /* PhoneManager.m in Sources */,
452E3C8E1D935C77002A45B0 /* OWSConversationSettingsTableViewController.m in Sources */,
E197B60F18BBEC1A00F073E5 /* EncodedAudioFrame.m in Sources */,
34535D821E256BE9008A4747 /* UIView+OWS.m in Sources */,
76EB061818170B33006006FC /* AnonymousValueLogger.m in Sources */,
76EB05E618170B33006006FC /* CallController.m in Sources */,
FC31962A1A067D8F0094C78E /* MessageComposeTableViewController.m in Sources */,

View File

@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "67EEE5C28C29FF38DA320F2E9F2B8666"
BlueprintIdentifier = "3B95C6D0A8DCB0450154B28670B6343E"
BuildableName = "libSignalServiceKit.a"
BlueprintName = "SignalServiceKit"
ReferencedContainer = "container:Pods/Pods.xcodeproj">

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "video-active.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "video-inactive.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -1,6 +1,7 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "AppAudioManager.h"
@ -13,11 +14,14 @@
#import "OWSWebRTCDataProtos.pb.h"
#import "PhoneNumber.h"
#import "PropertyListPreferences.h"
#import "PureLayout.h"
#import "PushManager.h"
#import "RPAccountManager.h"
#import "TSSocketManager.h"
#import "UIColor+OWS.h"
#import "UIFont+OWS.h"
#import "UIUtil.h"
#import "UIView+OWS.h"
#import <SignalServiceKit/Contact.h>
#import <SignalServiceKit/Cryptography.h>
#import <SignalServiceKit/NSData+Base64.h>

View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="15G1212" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="tuk-0x-yCb">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1212" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="tuk-0x-yCb">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
@ -129,10 +129,10 @@
</objects>
<point key="canvasLocation" x="-2287" y="-1516"/>
</scene>
<!--Current Call-->
<!--New Call-->
<scene sceneID="Xck-Ph-UlV">
<objects>
<viewController title="Current Call" definesPresentationContext="YES" modalTransitionStyle="crossDissolve" modalPresentationStyle="currentContext" id="Tyf-mN-gzf" customClass="OWSCallViewController" sceneMemberID="viewController">
<viewController storyboardIdentifier="OWSCallViewController" title="New Call" definesPresentationContext="YES" modalTransitionStyle="crossDissolve" modalPresentationStyle="currentContext" id="Tyf-mN-gzf" customClass="OWSCallViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="0w2-kv-AfM"/>
<viewControllerLayoutGuide type="bottom" id="d8M-LU-Hfa"/>
@ -140,216 +140,7 @@
<view key="view" contentMode="scaleToFill" id="fjB-Ns-OQs">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uej-BZ-jAb">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="Kr3-nb-TPK">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
<blurEffect style="dark"/>
</visualEffectView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bgz-d3-b1N" userLabel="Contact Container">
<rect key="frame" x="28" y="20" width="319" height="334.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="calling mobile ..." lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XWw-3X-PNN">
<rect key="frame" x="0.0" y="71" width="319" height="28"/>
<constraints>
<constraint firstAttribute="height" constant="28" id="mYD-Hx-NRM"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="id3-xi-PFz" customClass="AvatarImageView" customModule="Signal" customModuleProvider="target">
<rect key="frame" x="82.5" y="129" width="155.5" height="155.5"/>
<constraints>
<constraint firstAttribute="width" secondItem="id3-xi-PFz" secondAttribute="height" multiplier="1:1" id="Tfc-PI-hRy"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Emma Goldman" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UbL-8Z-oK1">
<rect key="frame" x="0.0" y="32" width="319" height="39"/>
<constraints>
<constraint firstAttribute="height" constant="39" id="Gvs-2Y-TYi"/>
</constraints>
<fontDescription key="fontDescription" type="system" weight="light" pointSize="32"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="XWw-3X-PNN" firstAttribute="top" secondItem="UbL-8Z-oK1" secondAttribute="bottom" id="5RT-FQ-bI8"/>
<constraint firstItem="id3-xi-PFz" firstAttribute="centerX" secondItem="bgz-d3-b1N" secondAttribute="centerX" id="7it-02-4fC"/>
<constraint firstItem="XWw-3X-PNN" firstAttribute="leading" secondItem="bgz-d3-b1N" secondAttribute="leading" id="EgA-RW-icW"/>
<constraint firstItem="UbL-8Z-oK1" firstAttribute="leading" secondItem="bgz-d3-b1N" secondAttribute="leading" id="G32-rI-2ce"/>
<constraint firstAttribute="bottom" secondItem="id3-xi-PFz" secondAttribute="bottom" constant="50" id="VnJ-m2-aUj"/>
<constraint firstAttribute="trailing" secondItem="XWw-3X-PNN" secondAttribute="trailing" id="aDA-Aj-66D"/>
<constraint firstItem="UbL-8Z-oK1" firstAttribute="top" secondItem="bgz-d3-b1N" secondAttribute="top" constant="32" id="pRt-uC-KIw"/>
<constraint firstItem="id3-xi-PFz" firstAttribute="top" secondItem="XWw-3X-PNN" secondAttribute="bottom" constant="30" id="qVE-XG-OAR"/>
<constraint firstAttribute="trailing" secondItem="UbL-8Z-oK1" secondAttribute="trailing" id="xmD-aB-zJj"/>
</constraints>
</view>
<view opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" translatesAutoresizingMaskIntoConstraints="NO" id="6aP-bG-6qH" userLabel="Call Controls">
<rect key="frame" x="0.0" y="354.5" width="375" height="200"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Dfe-Kk-RoU" userLabel="Top Row">
<rect key="frame" x="0.0" y="0.0" width="375" height="80"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NES-Ce-PcK" userLabel="Mute">
<rect key="frame" x="39" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="height" constant="80" id="IQT-LY-p9i"/>
<constraint firstAttribute="width" constant="80" id="ZIe-VD-8Mc"/>
</constraints>
<state key="normal" image="mute-inactive">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected" image="mute-active"/>
<connections>
<action selector="didPressMuteWithSender:" destination="Tyf-mN-gzf" eventType="touchUpInside" id="ko9-U2-m5M"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Bb2-w8-mPU" userLabel="Speaker">
<rect key="frame" x="255" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="width" constant="80" id="en7-kS-BRE"/>
<constraint firstAttribute="height" constant="80" id="ra6-Jk-V6g"/>
</constraints>
<state key="normal" image="speaker-inactive">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected" image="speaker-active"/>
<connections>
<action selector="didPressSpeakerphoneWithSender:" destination="Tyf-mN-gzf" eventType="touchUpInside" id="VbQ-qg-gmn"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VBi-XB-xTO" userLabel="Message">
<rect key="frame" x="147" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="width" constant="80" id="Bn4-cs-jmd"/>
<constraint firstAttribute="height" constant="80" id="bvL-na-JU4"/>
</constraints>
<state key="normal" image="logoSignal">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<state key="selected" image="mute-active"/>
</button>
</subviews>
<constraints>
<constraint firstItem="Bb2-w8-mPU" firstAttribute="centerY" secondItem="Dfe-Kk-RoU" secondAttribute="centerY" id="8m5-B0-bmL"/>
<constraint firstItem="NES-Ce-PcK" firstAttribute="centerY" secondItem="Dfe-Kk-RoU" secondAttribute="centerY" id="LaE-2R-kF3"/>
<constraint firstAttribute="height" constant="80" id="R3K-0P-4g0"/>
<constraint firstItem="Bb2-w8-mPU" firstAttribute="leading" secondItem="VBi-XB-xTO" secondAttribute="trailing" constant="28" id="e1y-c2-cnF"/>
<constraint firstItem="VBi-XB-xTO" firstAttribute="centerX" secondItem="Dfe-Kk-RoU" secondAttribute="centerX" id="kMb-az-s1i"/>
<constraint firstItem="VBi-XB-xTO" firstAttribute="leading" secondItem="NES-Ce-PcK" secondAttribute="trailing" constant="28" id="rQ0-Ca-K3s"/>
<constraint firstItem="VBi-XB-xTO" firstAttribute="centerY" secondItem="Dfe-Kk-RoU" secondAttribute="centerY" id="z7C-hz-PCx"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HOb-Yz-o3O" userLabel="Bottom Row">
<rect key="frame" x="0.0" y="120" width="375" height="80"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="iSB-Wx-bHp" userLabel="Hang Up">
<rect key="frame" x="147.5" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="height" constant="80" id="Wj8-Pk-fTC"/>
<constraint firstAttribute="width" secondItem="iSB-Wx-bHp" secondAttribute="height" multiplier="1:1" id="m67-U4-0tb"/>
</constraints>
<state key="normal" image="endcall.png"/>
<connections>
<action selector="didPressHangupWithSender:" destination="Tyf-mN-gzf" eventType="touchUpInside" id="bG7-oV-BIA"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="iSB-Wx-bHp" firstAttribute="centerY" secondItem="HOb-Yz-o3O" secondAttribute="centerY" id="UIW-TY-NOh"/>
<constraint firstItem="iSB-Wx-bHp" firstAttribute="centerX" secondItem="HOb-Yz-o3O" secondAttribute="centerX" id="WnN-Bn-Ohu"/>
<constraint firstAttribute="height" constant="80" id="YyR-vw-WDS"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="Dfe-Kk-RoU" firstAttribute="leading" secondItem="6aP-bG-6qH" secondAttribute="leading" id="34q-ot-2uZ"/>
<constraint firstAttribute="trailing" secondItem="HOb-Yz-o3O" secondAttribute="trailing" id="AO4-C5-Sca"/>
<constraint firstAttribute="bottom" secondItem="HOb-Yz-o3O" secondAttribute="bottom" id="FFb-Oi-psa"/>
<constraint firstItem="HOb-Yz-o3O" firstAttribute="leading" secondItem="6aP-bG-6qH" secondAttribute="leading" id="HgC-9f-j7X"/>
<constraint firstAttribute="trailing" secondItem="Dfe-Kk-RoU" secondAttribute="trailing" id="Nis-dZ-voT"/>
<constraint firstItem="Dfe-Kk-RoU" firstAttribute="top" secondItem="6aP-bG-6qH" secondAttribute="top" id="tJF-wT-zni"/>
<constraint firstItem="HOb-Yz-o3O" firstAttribute="top" secondItem="Dfe-Kk-RoU" secondAttribute="bottom" constant="40" id="uux-HY-Dp1"/>
</constraints>
</view>
<view opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" translatesAutoresizingMaskIntoConstraints="NO" id="5E5-dq-23I" userLabel="Incoming Call Controls">
<rect key="frame" x="0.0" y="571" width="375" height="96"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qtF-I8-OlZ" userLabel="Bottom Row">
<rect key="frame" x="0.0" y="0.0" width="375" height="80"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tqx-VV-3f1" userLabel="Hang Up">
<rect key="frame" x="39.5" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="width" secondItem="tqx-VV-3f1" secondAttribute="height" multiplier="1:1" id="LSQ-AP-Ojt"/>
<constraint firstAttribute="height" constant="80" id="g3g-jD-jeK"/>
</constraints>
<state key="normal" image="endcall.png"/>
<connections>
<action selector="didPressDeclineCallWithSender:" destination="Tyf-mN-gzf" eventType="touchUpInside" id="9BJ-eS-7AG"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="TUk-K2-YSx" userLabel="Answer">
<rect key="frame" x="255.5" y="0.0" width="80" height="80"/>
<constraints>
<constraint firstAttribute="height" constant="80" id="1rO-db-thZ"/>
<constraint firstAttribute="width" secondItem="TUk-K2-YSx" secondAttribute="height" multiplier="1:1" id="d6N-G5-flo"/>
</constraints>
<state key="normal" image="call.png"/>
<connections>
<action selector="didPressAnswerCallWithSender:" destination="Tyf-mN-gzf" eventType="touchUpInside" id="Nsy-gL-24V"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="TUk-K2-YSx" firstAttribute="centerY" secondItem="qtF-I8-OlZ" secondAttribute="centerY" id="8of-qZ-3g6"/>
<constraint firstItem="TUk-K2-YSx" firstAttribute="centerX" secondItem="qtF-I8-OlZ" secondAttribute="centerX" constant="108" id="BwS-B7-UFj"/>
<constraint firstAttribute="height" constant="80" id="a38-ig-Vdx"/>
<constraint firstItem="tqx-VV-3f1" firstAttribute="centerX" secondItem="qtF-I8-OlZ" secondAttribute="centerX" constant="-108" id="a7f-sa-u5E"/>
<constraint firstItem="tqx-VV-3f1" firstAttribute="centerY" secondItem="qtF-I8-OlZ" secondAttribute="centerY" id="hEK-8j-k8P"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="qtF-I8-OlZ" firstAttribute="top" secondItem="5E5-dq-23I" secondAttribute="top" id="0rH-Ib-QGg"/>
<constraint firstAttribute="bottom" secondItem="qtF-I8-OlZ" secondAttribute="bottom" constant="16" id="m7r-9Q-dbe"/>
<constraint firstItem="qtF-I8-OlZ" firstAttribute="leading" secondItem="5E5-dq-23I" secondAttribute="leading" id="uOS-TT-KF0"/>
<constraint firstAttribute="trailing" secondItem="qtF-I8-OlZ" secondAttribute="trailing" id="uja-WP-bxH"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="uej-BZ-jAb" secondAttribute="trailing" id="6mk-1V-qHZ"/>
<constraint firstItem="6aP-bG-6qH" firstAttribute="top" secondItem="bgz-d3-b1N" secondAttribute="bottom" id="714-6d-zm0"/>
<constraint firstItem="uej-BZ-jAb" firstAttribute="leading" secondItem="fjB-Ns-OQs" secondAttribute="leading" id="ClP-il-Yf3"/>
<constraint firstItem="bgz-d3-b1N" firstAttribute="top" secondItem="0w2-kv-AfM" secondAttribute="bottom" id="GIA-x8-Ugw"/>
<constraint firstItem="d8M-LU-Hfa" firstAttribute="top" relation="greaterThanOrEqual" secondItem="6aP-bG-6qH" secondAttribute="bottom" id="M1W-xS-Rly"/>
<constraint firstItem="d8M-LU-Hfa" firstAttribute="top" secondItem="5E5-dq-23I" secondAttribute="bottom" id="TX0-VF-EdJ"/>
<constraint firstItem="d8M-LU-Hfa" firstAttribute="top" secondItem="uej-BZ-jAb" secondAttribute="bottom" id="UMq-wM-QrB"/>
<constraint firstItem="bgz-d3-b1N" firstAttribute="height" secondItem="fjB-Ns-OQs" secondAttribute="height" multiplier="1:2" constant="1" id="YGm-Ij-xfM"/>
<constraint firstAttribute="trailing" secondItem="6aP-bG-6qH" secondAttribute="trailing" id="dw7-6I-6ja"/>
<constraint firstItem="5E5-dq-23I" firstAttribute="leading" secondItem="fjB-Ns-OQs" secondAttribute="leading" id="ig5-hm-72O"/>
<constraint firstItem="uej-BZ-jAb" firstAttribute="top" secondItem="0w2-kv-AfM" secondAttribute="bottom" constant="-20" id="qV1-mQ-MCP"/>
<constraint firstItem="6aP-bG-6qH" firstAttribute="leading" secondItem="fjB-Ns-OQs" secondAttribute="leading" id="rD8-nc-45P"/>
<constraint firstAttribute="trailing" secondItem="5E5-dq-23I" secondAttribute="trailing" id="rTC-1c-nvO"/>
<constraint firstAttribute="trailingMargin" secondItem="bgz-d3-b1N" secondAttribute="trailing" constant="12" id="tGv-Vo-kls"/>
<constraint firstItem="bgz-d3-b1N" firstAttribute="leading" secondItem="fjB-Ns-OQs" secondAttribute="leadingMargin" constant="12" id="uCE-8S-LvK"/>
</constraints>
</view>
<connections>
<outlet property="callControls" destination="6aP-bG-6qH" id="out-ek-gWQ"/>
<outlet property="callStatusLabel" destination="XWw-3X-PNN" id="GIf-J0-uGc"/>
<outlet property="contactAvatarView" destination="id3-xi-PFz" id="CUV-hJ-Qcp"/>
<outlet property="contactNameLabel" destination="UbL-8Z-oK1" id="h9V-l9-JVF"/>
<outlet property="incomingCallControls" destination="5E5-dq-23I" id="fWz-1n-pjI"/>
<outlet property="muteButton" destination="NES-Ce-PcK" id="Eku-Tx-cMN"/>
<outlet property="speakerPhoneButton" destination="Bb2-w8-mPU" id="GYN-Z6-i5I"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="5mi-rT-gg5" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
@ -640,7 +431,7 @@
<rect key="frame" x="0.0" y="144" width="375" height="108"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="U6h-Xo-HEv" id="Nmz-2u-fOY">
<rect key="frame" x="0.0" y="0.0" width="375" height="107"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="108"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Disappearing Messages" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="qbY-qJ-enK" userLabel="Disappearing Messages">
@ -696,7 +487,7 @@
<rect key="frame" x="0.0" y="252" width="375" height="76"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3dL-aW-P1A" id="2a2-Po-p8O">
<rect key="frame" x="0.0" y="0.0" width="375" height="75"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="76"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Messages disappear after 8 hours." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="c6Q-rV-1LO" userLabel="Keep messages for 8 hours.">
@ -742,7 +533,7 @@
<tableViewSection headerTitle="Group Management" id="z5m-Fe-GK8">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="NxZ-wa-xV9" style="IBUITableViewCellStyleDefault" id="XHr-b6-Gvn" userLabel="Update Group">
<rect key="frame" x="0.0" y="385" width="375" height="44"/>
<rect key="frame" x="0.0" y="384" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="XHr-b6-Gvn" id="Epj-vT-UYL">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
@ -762,7 +553,7 @@
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="geN-YN-TQg" style="IBUITableViewCellStyleDefault" id="w57-rz-BWN" userLabel="Leave Group">
<rect key="frame" x="0.0" y="429" width="375" height="44"/>
<rect key="frame" x="0.0" y="428" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="w57-rz-BWN" id="Pgy-Fc-U25">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
@ -779,7 +570,7 @@
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="Zml-Zn-2fd" style="IBUITableViewCellStyleDefault" id="Dnq-Ko-46l" userLabel="Group Members">
<rect key="frame" x="0.0" y="473" width="375" height="44"/>
<rect key="frame" x="0.0" y="472" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Dnq-Ko-46l" id="VRQ-31-E5Y">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
@ -844,7 +635,7 @@
<rect key="frame" x="0.0" y="22" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hyn-Ss-OAa" id="4XE-JO-Upr">
<rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</tableViewCellContentView>
</tableViewCell>
@ -860,10 +651,10 @@
</objects>
<point key="canvasLocation" x="-1032" y="-1540"/>
</scene>
<!--2.0_6.0 - Incoming, Outgoing, Active call-->
<!--Old Call-->
<scene sceneID="cEC-6y-6yI">
<objects>
<viewController storyboardIdentifier="InCallViewController" definesPresentationContext="YES" modalTransitionStyle="crossDissolve" modalPresentationStyle="currentContext" id="Duq-aU-MmN" userLabel="2.0_6.0 - Incoming, Outgoing, Active call" customClass="InCallViewController" sceneMemberID="viewController">
<viewController storyboardIdentifier="InCallViewController" title="Old Call" definesPresentationContext="YES" modalTransitionStyle="crossDissolve" modalPresentationStyle="currentContext" id="Duq-aU-MmN" customClass="InCallViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="g84-iS-Sgw"/>
<viewControllerLayoutGuide type="bottom" id="9Ut-k6-hNn"/>
@ -1145,7 +936,7 @@
<rect key="frame" x="0.0" y="56" width="375" height="72"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="XjV-oU-jSb" id="XqL-QG-IbY">
<rect key="frame" x="0.0" y="0.0" width="375" height="71"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="72"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Signal on Chrome" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="57o-uV-YOg">
@ -1189,18 +980,18 @@
<rect key="frame" x="0.0" y="128" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="6h2-gg-1C6" id="RKi-c6-pzb">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Link New Device" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="w80-IJ-E6R">
<rect key="frame" x="15" y="3" width="127" height="21"/>
<rect key="frame" x="15" y="4" width="127" height="20.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Scan QR Code" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8ft-2u-wBF">
<rect key="frame" x="15" y="24" width="88" height="16"/>
<rect key="frame" x="15" y="24.5" width="88" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1255,7 +1046,7 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5zF-Ko-9qU" id="gr7-Sm-bcs">
<rect key="frame" x="0.0" y="0.0" width="375" height="95"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1 (708) 000-1234" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ipE-BI-sLL">
@ -1296,7 +1087,7 @@
<rect key="frame" x="0.0" y="96" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8rk-06-1ZS" id="hqv-P5-du9">
<rect key="frame" x="0.0" y="0.0" width="375" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
@ -1353,11 +1144,11 @@
<rect key="frame" x="0.0" y="184" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ITG-sW-Zn0" id="vOb-SA-SH2">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Privacy" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="i1f-DT-7rL">
<rect key="frame" x="15" y="0.0" width="325" height="43"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1370,11 +1161,11 @@
<rect key="frame" x="0.0" y="228" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jp5-vZ-AhJ" id="sji-CJ-bhq">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Notifications" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tRQ-1p-6aT">
<rect key="frame" x="15" y="0.0" width="325" height="43"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1387,11 +1178,11 @@
<rect key="frame" x="0.0" y="272" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wZ8-fs-Ylw" id="Ua5-nw-s2z">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Linked Devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hrc-lZ-NeA">
<rect key="frame" x="15" y="0.0" width="325" height="43"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1407,11 +1198,11 @@
<rect key="frame" x="0.0" y="316" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Xx7-pz-aLN" id="pMA-vR-8Ae">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Advanced" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dkL-Nz-E6H">
<rect key="frame" x="15" y="0.0" width="325" height="43"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1424,11 +1215,11 @@
<rect key="frame" x="0.0" y="360" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EI4-kQ-MMA" id="czg-5p-aVz">
<rect key="frame" x="0.0" y="0.0" width="342" height="43"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="About" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qeN-f1-cIQ">
<rect key="frame" x="15" y="0.0" width="325" height="43"/>
<rect key="frame" x="15" y="0.0" width="325" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1445,7 +1236,7 @@
<rect key="frame" x="0.0" y="404" width="375" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="R82-FT-SEA" id="Ok9-fE-WhB">
<rect key="frame" x="0.0" y="0.0" width="375" height="99"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4Mk-ly-6fq">
@ -1630,7 +1421,7 @@
<rect key="frame" x="0.0" y="22" width="375" height="59"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Ld5-sX-pB8" id="EqP-87-4hZ">
<rect key="frame" x="0.0" y="0.0" width="375" height="58"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="59"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4zF-SU-q4z">
@ -1696,11 +1487,11 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Pgm-Qb-oPu" id="amG-75-RNT">
<rect key="frame" x="0.0" y="0.0" width="342" height="47"/>
<rect key="frame" x="0.0" y="0.0" width="342" height="47.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Invite your friends!" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QGl-1D-W9D">
<rect key="frame" x="15" y="0.0" width="325" height="47"/>
<rect key="frame" x="15" y="0.0" width="325" height="47.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" red="0.09412795243864841" green="0.43645224658557435" blue="0.71380208333333339" alpha="1" colorSpace="calibratedRGB"/>
@ -1792,11 +1583,11 @@
<rect key="frame" x="0.0" y="62" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="yfF-Jl-bZ1" id="f0v-od-N9K">
<rect key="frame" x="0.0" y="0.0" width="375" height="59"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="a4j-OQ-ala">
<rect key="frame" x="15" y="0.0" width="345" height="59"/>
<rect key="frame" x="15" y="0.0" width="345" height="59.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@ -1890,7 +1681,6 @@
<image name="endcall.png" width="100" height="100"/>
<image name="ic_devices_ios" width="180" height="119"/>
<image name="ic_lock_outline" width="32" height="32"/>
<image name="logoSignal" width="138" height="139"/>
<image name="mute-active" width="80" height="80"/>
<image name="mute-inactive" width="80" height="80"/>
<image name="settings" width="44" height="44"/>
@ -1905,8 +1695,8 @@
<simulatedScreenMetrics key="destination" type="retina4_7.fullscreen"/>
</simulatedMetricsContainer>
<inferredMetricsTieBreakers>
<segue reference="wgA-Oo-kKq"/>
<segue reference="E8S-Yc-X7E"/>
<segue reference="G2B-Fr-Ezs"/>
<segue reference="tfr-ZV-qWs"/>
<segue reference="E8S-Yc-X7E"/>
</inferredMetricsTieBreakers>
</document>

51
Signal/src/UIView+OWS.h Normal file
View File

@ -0,0 +1,51 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <UIKit/UIKit.h>
// A convenience method for doing responsive layout. Scales between two
// reference values (for iPhone 5 and iPhone 7 Plus) to the current device
// based on screen width, linearly interpolating.
CGFloat ScaleFromIPhone5To7Plus(CGFloat iPhone5Value, CGFloat iPhone7PlusValue);
// A convenience method for doing responsive layout. Scales a reference
// value (for iPhone 5) to the current device based on screen width,
// linearly interpolating through the origin.
CGFloat ScaleFromIPhone5(CGFloat iPhone5Value);
// A set of helper methods for doing layout with PureLayout.
@interface UIView (OWS)
// Pins the width of this view to the width of its superview, with uniform margins.
- (void)autoPinWidthToSuperviewWithMargin:(CGFloat)margin;
- (void)autoPinWidthToSuperview;
// Pins the height of this view to the height of its superview, with uniform margins.
- (void)autoPinHeightToSuperviewWithMargin:(CGFloat)margin;
- (void)autoPinHeightToSuperview;
- (void)autoHCenterInSuperview;
- (void)autoVCenterInSuperview;
#pragma mark - Content Hugging and Compression Resistance
- (void)setContentHuggingLow;
- (void)setContentHuggingHigh;
- (void)setContentHuggingHorizontalLow;
- (void)setContentHuggingHorizontalHigh;
- (void)setContentHuggingVerticalLow;
- (void)setContentHuggingVerticalHigh;
- (void)setCompressionResistanceLow;
- (void)setCompressionResistanceHigh;
- (void)setCompressionResistanceHorizontalLow;
- (void)setCompressionResistanceHorizontalHigh;
- (void)setCompressionResistanceVerticalLow;
- (void)setCompressionResistanceVerticalHigh;
#pragma mark - Debugging
- (void)addBorderWithColor:(UIColor *)color;
- (void)addRedBorder;
@end

170
Signal/src/UIView+OWS.m Normal file
View File

@ -0,0 +1,170 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "PureLayout.h"
#import "UIView+OWS.h"
// TODO: We'll eventually want to promote these into an OWSMath.h header.
static inline CGFloat Clamp(CGFloat value, CGFloat minValue, CGFloat maxValue)
{
return MAX(minValue, MIN(maxValue, value));
}
static inline CGFloat Clamp01(CGFloat value)
{
return Clamp(value, 0.f, 1.f);
}
static inline CGFloat CGFloatLerp(CGFloat left, CGFloat right, CGFloat alpha)
{
alpha = Clamp01(alpha);
return (left * (1.f - alpha)) + (right * alpha);
}
static inline CGFloat CGFloatInverseLerp(CGFloat value, CGFloat minValue, CGFloat maxValue)
{
return (value - minValue) / (maxValue - minValue);
}
static inline CGFloat ScreenShortDimension()
{
return MIN([UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
}
static const CGFloat kIPhone5ScreenWidth = 320.f;
static const CGFloat kIPhone7PlusScreenWidth = 414.f;
CGFloat ScaleFromIPhone5To7Plus(CGFloat iPhone5Value, CGFloat iPhone7PlusValue)
{
CGFloat screenShortDimension = ScreenShortDimension();
return round(CGFloatLerp(iPhone5Value,
iPhone7PlusValue,
CGFloatInverseLerp(screenShortDimension, kIPhone5ScreenWidth, kIPhone7PlusScreenWidth)));
}
CGFloat ScaleFromIPhone5(CGFloat iPhone5Value)
{
CGFloat screenShortDimension = ScreenShortDimension();
return round(iPhone5Value * screenShortDimension / kIPhone5ScreenWidth);
}
#pragma mark -
@implementation UIView (OWS)
- (void)autoPinWidthToSuperviewWithMargin:(CGFloat)margin
{
[self autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:self.superview withOffset:+margin];
[self autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.superview withOffset:-margin];
}
- (void)autoPinWidthToSuperview
{
[self autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:self.superview];
[self autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.superview];
}
- (void)autoPinHeightToSuperviewWithMargin:(CGFloat)margin
{
[self autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:self.superview withOffset:+margin];
[self autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:self.superview withOffset:-margin];
}
- (void)autoPinHeightToSuperview
{
[self autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:self.superview];
[self autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:self.superview];
}
- (void)autoHCenterInSuperview
{
[self autoAlignAxis:ALAxisVertical toSameAxisOfView:self.superview];
}
- (void)autoVCenterInSuperview
{
[self autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.superview];
}
#pragma mark - Content Hugging and Compression Resistance
- (void)setContentHuggingLow
{
[self setContentHuggingHorizontalLow];
[self setContentHuggingVerticalLow];
}
- (void)setContentHuggingHigh
{
[self setContentHuggingHorizontalHigh];
[self setContentHuggingVerticalHigh];
}
- (void)setContentHuggingHorizontalLow
{
[self setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
}
- (void)setContentHuggingHorizontalHigh
{
[self setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
}
- (void)setContentHuggingVerticalLow
{
[self setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisVertical];
}
- (void)setContentHuggingVerticalHigh
{
[self setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}
- (void)setCompressionResistanceLow
{
[self setCompressionResistanceHorizontalLow];
[self setCompressionResistanceVerticalLow];
}
- (void)setCompressionResistanceHigh
{
[self setCompressionResistanceHorizontalHigh];
[self setCompressionResistanceVerticalHigh];
}
- (void)setCompressionResistanceHorizontalLow
{
[self setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisHorizontal];
}
- (void)setCompressionResistanceHorizontalHigh
{
[self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
}
- (void)setCompressionResistanceVerticalLow
{
[self setContentCompressionResistancePriority:0 forAxis:UILayoutConstraintAxisVertical];
}
- (void)setCompressionResistanceVerticalHigh
{
[self setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
}
#pragma mark - Debugging
- (void)addBorderWithColor:(UIColor *)color
{
self.layer.borderColor = color.CGColor;
self.layer.borderWidth = 1;
}
- (void)addRedBorder
{
[self addBorderWithColor:[UIColor redColor]];
}
@end

View File

@ -1,5 +1,6 @@
// Created by Michael Kirk on 12/7/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
import Foundation
@ -60,7 +61,7 @@ protocol CallDelegate: class {
}
class func outgoingCall(localId: UUID, remotePhoneNumber: String) -> SignalCall {
return SignalCall(localId: localId, signalingId: UInt64.ows_random(), state: .dialing, remotePhoneNumber: remotePhoneNumber)
return SignalCall(localId: localId, signalingId: newCallSignalingId(), state: .dialing, remotePhoneNumber: remotePhoneNumber)
}
class func incomingCall(localId: UUID, remotePhoneNumber: String, signalingId: UInt64) -> SignalCall {
@ -72,6 +73,9 @@ protocol CallDelegate: class {
return lhs.localId == rhs.localId
}
static func newCallSignalingId() -> UInt64 {
return UInt64.ows_random()
}
}
fileprivate extension UInt64 {

View File

@ -1,5 +1,6 @@
// Created by Michael Kirk on 11/10/16.
// Copyright © 2016 Open Whisper Systems. All rights reserved.
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
import Foundation
import WebRTC
@ -136,7 +137,7 @@ class CallViewController: UIViewController, CallDelegate {
let TAG = "[CallViewController]"
// Dependencies
let callUIAdapter: CallUIAdapter
let contactsManager: OWSContactsManager
let audioService: CallAudioService
@ -148,19 +149,36 @@ class CallViewController: UIViewController, CallDelegate {
var thread: TSContactThread!
var call: SignalCall!
@IBOutlet weak var contactNameLabel: UILabel!
@IBOutlet weak var contactAvatarView: AvatarImageView!
@IBOutlet weak var callStatusLabel: UILabel!
// MARK: Layout
// MARK: Outgoing or Accepted Call Controls
var hasConstraints = false
@IBOutlet weak var callControls: UIView!
@IBOutlet weak var muteButton: UIButton!
@IBOutlet weak var speakerPhoneButton: UIButton!
// MARK: Background
var blurView: UIVisualEffectView!
// MARK: Contact Views
var contactNameLabel: UILabel!
var contactAvatarView: AvatarImageView!
var callStatusLabel: UILabel!
// MARK: Ongoing Call Controls
var ongoingCallView: UIView!
var hangUpButton: UIButton!
var muteButton: UIButton!
var speakerPhoneButton: UIButton!
// TODO: Which call states does this apply to?
var textMessageButton: UIButton!
var videoButton: UIButton!
// MARK: Incoming Call Controls
@IBOutlet weak var incomingCallControls: UIView!
var incomingCallControlsRow: UIView!
var acceptIncomingButton: UIButton!
var declineIncomingButton: UIButton!
// MARK: Initializers
@ -181,6 +199,7 @@ class CallViewController: UIViewController, CallDelegate {
}
override func viewDidLoad() {
super.viewDidLoad()
guard let thread = self.thread else {
Logger.error("\(TAG) tried to show call call without specifying thread.")
@ -188,6 +207,8 @@ class CallViewController: UIViewController, CallDelegate {
return
}
createViews()
contactNameLabel.text = contactsManager.displayName(forPhoneIdentifier: thread.contactIdentifier())
contactAvatarView.image = OWSAvatarBuilder.buildImage(for: thread, contactsManager: contactsManager)
@ -206,6 +227,191 @@ class CallViewController: UIViewController, CallDelegate {
stateDidChange(call: call, state: call.state)
}
func createViews() {
// Dark blurred background.
let blurEffect = UIBlurEffect(style: .dark)
blurView = UIVisualEffectView(effect: blurEffect)
self.view.addSubview(blurView)
// Contact views
contactNameLabel = UILabel()
contactNameLabel.font = UIFont.ows_lightFont(withSize:ScaleFromIPhone5To7Plus(32, 40))
contactNameLabel.textColor = UIColor.white
self.view.addSubview(contactNameLabel)
callStatusLabel = UILabel()
callStatusLabel.font = UIFont.ows_regularFont(withSize:ScaleFromIPhone5To7Plus(19, 25))
callStatusLabel.textColor = UIColor.white
self.view.addSubview(callStatusLabel)
contactAvatarView = AvatarImageView()
self.view.addSubview(contactAvatarView)
// Ongoing call controls
let buttonSize = ScaleFromIPhone5To7Plus(70, 90)
textMessageButton = createButton(imageName:"logoSignal",
action:#selector(didPressTextMessage),
buttonSize:buttonSize)
muteButton = createButton(imageName:"mute-inactive",
action:#selector(didPressMute),
buttonSize:buttonSize)
speakerPhoneButton = createButton(imageName:"speaker-inactive",
action:#selector(didPressSpeakerphone),
buttonSize:buttonSize)
videoButton = createButton(imageName:"video-active",
action:#selector(didPressVideo),
buttonSize:buttonSize)
hangUpButton = createButton(imageName:"endcall",
action:#selector(didPressHangup),
buttonSize:buttonSize)
// A container for 3 rows of ongoing call controls.
ongoingCallView = UIView()
self.view.addSubview(ongoingCallView)
let ongoingCallRows = [
rowWithSubviews(subviews:[textMessageButton, videoButton],
fixedHeight:buttonSize),
rowWithSubviews(subviews:[muteButton, speakerPhoneButton, ],
fixedHeight:buttonSize),
rowWithSubviews(subviews:[hangUpButton],
fixedHeight:buttonSize),
]
let ongoingCallRowSpacing = ScaleFromIPhone5To7Plus(20, 25)
var lastRow: UIView?
for row in ongoingCallRows {
ongoingCallView.addSubview(row)
row.autoPinWidthToSuperview()
if lastRow != nil {
row.autoPinEdge(.top, to:.bottom, of:lastRow!, withOffset:ongoingCallRowSpacing)
}
lastRow = row
}
ongoingCallView.setContentHuggingVerticalHigh()
ongoingCallRows.first!.autoPinEdge(toSuperviewEdge:.top)
ongoingCallRows.last!.autoPinEdge(toSuperviewEdge:.bottom)
// Incoming call controls
acceptIncomingButton = createButton(imageName:"call",
action:#selector(didPressAnswerCall),
buttonSize:buttonSize)
declineIncomingButton = createButton(imageName:"endcall",
action:#selector(didPressDeclineCall),
buttonSize:buttonSize)
incomingCallControlsRow = rowWithSubviews(subviews:[acceptIncomingButton, declineIncomingButton],
fixedHeight:buttonSize)
self.view.addSubview(incomingCallControlsRow)
}
func createButton(imageName: String!, action: Selector!, buttonSize: CGFloat!) -> UIButton {
let image = UIImage(named:imageName)
Logger.error("button \(imageName) \(NSStringFromCGSize(image!.size))")
Logger.flush()
let button = UIButton()
button.setImage(image, for:.normal)
button.addTarget(self, action:action, for:.touchUpInside)
button.autoSetDimension(.width, toSize:buttonSize)
button.autoSetDimension(.height, toSize:buttonSize)
return button
}
// Creates a row view that evenly spaces its subviews horizontally.
// If there is only a single subview, it is centered.
func rowWithSubviews(subviews: Array<UIButton>, fixedHeight: CGFloat) -> UIView {
let row = UIView()
row.setContentHuggingVerticalHigh()
row.autoSetDimension(.height, toSize:fixedHeight)
if subviews.count > 1 {
var lastSubview: UIView?
var lastSpacer: UIView?
for subview in subviews {
row.addSubview(subview)
subview.setContentHuggingHorizontalHigh()
subview.autoVCenterInSuperview()
if lastSubview != nil {
let spacer = UIView()
spacer.isHidden = true
row.addSubview(spacer)
spacer.autoPinEdge(.left, to:.right, of:lastSubview!)
spacer.autoPinEdge(.right, to:.left, of:subview)
spacer.setContentHuggingHorizontalLow()
spacer.autoVCenterInSuperview()
if lastSpacer != nil {
spacer.autoMatch(_:.width, to:.width, of:lastSpacer!)
}
lastSpacer = spacer
}
lastSubview = subview
}
subviews.first!.autoPinEdge(toSuperviewEdge:.left)
subviews.last!.autoPinEdge(toSuperviewEdge:.right)
Logger.error("row \(subviews.count) -> \(row.subviews.count)")
} else if subviews.count == 1 {
let subview = subviews.first!
row.addSubview(subview)
subview.autoCenterInSuperview()
}
return row
}
override func updateViewConstraints() {
if (!hasConstraints) {
// We only want to create our constraints once.
//
// Note that constraints are also created elsewhere.
// This only creates the constraints for the top-level contents of the view.
hasConstraints = true
let topMargin = CGFloat(40)
let contactHMargin = CGFloat(30)
let contactVSpacing = CGFloat(3)
let ongoingHMargin = ScaleFromIPhone5To7Plus(60, 90)
let incomingHMargin = ScaleFromIPhone5To7Plus(60, 90)
let ongoingBottomMargin = ScaleFromIPhone5To7Plus(30, 50)
let incomingBottomMargin = CGFloat(50)
let avatarVSpacing = ScaleFromIPhone5To7Plus(25, 50)
// Dark blurred background.
blurView.autoPinEdgesToSuperviewEdges()
contactNameLabel.autoPinEdge(toSuperviewEdge:.top, withInset:topMargin)
contactNameLabel.autoPinWidthToSuperview(withMargin:contactHMargin)
contactNameLabel.setContentHuggingVerticalHigh()
callStatusLabel.autoPinEdge(.top, to:.bottom, of:contactNameLabel, withOffset:contactVSpacing)
callStatusLabel.autoPinWidthToSuperview(withMargin:contactHMargin)
callStatusLabel.setContentHuggingVerticalHigh()
contactAvatarView.autoPinEdge(.top, to:.bottom, of:callStatusLabel, withOffset:+avatarVSpacing)
contactAvatarView.autoPinEdge(.bottom, to:.top, of:ongoingCallView, withOffset:-avatarVSpacing)
contactAvatarView.autoHCenterInSuperview()
// Stretch that avatar to fill the available space.
contactAvatarView.setContentHuggingLow()
contactAvatarView.setCompressionResistanceLow()
// Preserve square aspect ratio of contact avatar.
contactAvatarView.autoMatch(.width, to:.height, of:contactAvatarView)
// Ongoing call controls
ongoingCallView.autoPinEdge(toSuperviewEdge:.bottom, withInset:ongoingBottomMargin)
ongoingCallView.autoPinWidthToSuperview(withMargin:ongoingHMargin)
ongoingCallView.setContentHuggingVerticalHigh()
// Incoming call controls
incomingCallControlsRow.autoPinEdge(toSuperviewEdge:.bottom, withInset:incomingBottomMargin)
incomingCallControlsRow.autoPinWidthToSuperview(withMargin:incomingHMargin)
incomingCallControlsRow.setContentHuggingVerticalHigh()
}
super.updateViewConstraints()
}
// objc accessible way to set our swift enum.
func setOutgoingCallDirection() {
callDirection = .outgoing
@ -247,8 +453,18 @@ class CallViewController: UIViewController, CallDelegate {
self.callStatusLabel.text = textForState
// Show Incoming vs. (Outgoing || Accepted) call controls
callControls.isHidden = callState == .localRinging
incomingCallControls.isHidden = callState != .localRinging
let isRinging = callState == .localRinging
for subview in allControls() {
if isRinging {
// Show incoming controls
let isIncomingCallControl = incomingCallControls().contains(subview)
subview.isHidden = !isIncomingCallControl
} else {
// Show ongoing controls
let isOngoingCallControl = ongoingCallControls().contains(subview)
subview.isHidden = !isOngoingCallControl
}
}
// Dismiss Handling
switch callState {
@ -265,12 +481,25 @@ class CallViewController: UIViewController, CallDelegate {
}
}
func allControls() -> [UIView] {
return incomingCallControls() + ongoingCallControls()
}
func incomingCallControls() -> [UIView] {
// TODO: Should this include textMessageButton?
return [ acceptIncomingButton, declineIncomingButton, ]
}
func ongoingCallControls() -> [UIView] {
return [ muteButton, speakerPhoneButton, textMessageButton, hangUpButton, videoButton, ]
}
// MARK: - Actions
/**
* Ends a connected call. Do not confuse with `didPressDeclineCall`.
*/
@IBAction func didPressHangup(sender: UIButton) {
func didPressHangup(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
if let call = self.call {
callUIAdapter.endCall(call)
@ -281,7 +510,7 @@ class CallViewController: UIViewController, CallDelegate {
self.dismiss(animated: true)
}
@IBAction func didPressMute(sender muteButton: UIButton) {
func didPressMute(sender muteButton: UIButton) {
Logger.info("\(TAG) called \(#function)")
muteButton.isSelected = !muteButton.isSelected
if let call = self.call {
@ -291,13 +520,17 @@ class CallViewController: UIViewController, CallDelegate {
}
}
@IBAction func didPressSpeakerphone(sender speakerphoneButton: UIButton) {
func didPressSpeakerphone(sender speakerphoneButton: UIButton) {
Logger.info("\(TAG) called \(#function)")
speakerphoneButton.isSelected = !speakerphoneButton.isSelected
audioService.isSpeakerphoneEnabled = speakerphoneButton.isSelected
}
@IBAction func didPressAnswerCall(sender: UIButton) {
func didPressTextMessage(sender speakerphoneButton: UIButton) {
Logger.info("\(TAG) called \(#function)")
}
func didPressAnswerCall(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
guard let call = self.call else {
@ -312,10 +545,14 @@ class CallViewController: UIViewController, CallDelegate {
callUIAdapter.answerCall(call)
}
func didPressVideo(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
}
/**
* Denies an incoming not-yet-connected call, Do not confuse with `didPressHangup`.
*/
@IBAction func didPressDeclineCall(sender: UIButton) {
func didPressDeclineCall(sender: UIButton) {
Logger.info("\(TAG) called \(#function)")
if let call = self.call {