call view: improve UI / UX
- improve UI / UX: the view has been refactored
- add UIDevice extension allowing to know if the device has a notch or not
- doesn't show hours of the duration label when the call is under 1 hour
- management of the screen orientation for both audio and video calls
- the Name Label is showing bigger and the Duration label is showing smaller
- the UI has been adapted to the size of the iPhone 5
- fix the bug concerning the disappearance of the info and buttons containers
- show the Ring ID when the display name doesn't exist
Change-Id: I78203660603e451a2b088a3fcad1e64bbbe4f8e0
Reviewed-by: Kateryna Kostiuk<kateryna.kostiuk@savoirfairelinux.com>
diff --git a/Ring/Ring/Account/AccountModelHelper.swift b/Ring/Ring/Account/AccountModelHelper.swift
index 0e2ebca..89be041 100644
--- a/Ring/Ring/Account/AccountModelHelper.swift
+++ b/Ring/Ring/Account/AccountModelHelper.swift
@@ -133,10 +133,12 @@
let accountUsernameKey = ConfigKeyModel(withKey: ConfigKey.accountUsername)
let accountUsername = self.account.details?.get(withConfigKeyModel: accountUsernameKey)
-
- if accountUsername!.contains(AccountModelHelper.ringIdPrefix) {
- let index = accountUsername?.range(of: AccountModelHelper.ringIdPrefix)?.upperBound
- return accountUsername?.substring(from: index!)
+ guard let userName = accountUsername else {
+ return nil
+ }
+ if userName.contains(AccountModelHelper.ringIdPrefix) {
+ let index = userName.range(of: AccountModelHelper.ringIdPrefix)?.upperBound
+ return userName.substring(from: index!)
} else {
return nil
}
diff --git a/Ring/Ring/Calls/ButtonsContainerView.swift b/Ring/Ring/Calls/ButtonsContainerView.swift
index 9a0e5c7..ae5963a 100644
--- a/Ring/Ring/Calls/ButtonsContainerView.swift
+++ b/Ring/Ring/Calls/ButtonsContainerView.swift
@@ -23,6 +23,7 @@
class ButtonsContainerView: UIView, NibLoadable {
+ //Outlets
@IBOutlet var containerView: UIView!
@IBOutlet weak var container: UIView!
@IBOutlet weak var stackView: UIStackView!
@@ -33,12 +34,17 @@
@IBOutlet weak var switchCameraButton: UIButton!
@IBOutlet weak var switchSpeakerButton: UIButton!
@IBOutlet weak var cancelButton: UIButton!
- @IBOutlet weak var cancelButtonHeightConstraint: NSLayoutConstraint!
- @IBOutlet weak var containerHeightConstraint: NSLayoutConstraint!
- @IBOutlet weak var stackViewWidthConstraint: NSLayoutConstraint!
- @IBOutlet weak var stackViewBottomConstraint: NSLayoutConstraint!
+ //Constraints
+ @IBOutlet weak var cancelButtonWidthConstraint: NSLayoutConstraint!
+ @IBOutlet weak var cancelButtonBottomConstraint: NSLayoutConstraint!
+ @IBOutlet weak var cancelButtonHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var stackViewYConstraint: NSLayoutConstraint!
+ @IBOutlet weak var stackViewWidthConstraint: NSLayoutConstraint!
+ @IBOutlet weak var containerHeightConstraint: NSLayoutConstraint!
+
let disposeBag = DisposeBag()
+ var isCallStarted: Bool = false
var viewModel: ButtonsContainerViewModel? {
didSet {
@@ -73,7 +79,6 @@
guard let window = self.window else {
return
}
- self.container.bottomAnchor.constraint(equalTo: window.bottomAnchor).isActive = true
}
}
@@ -84,47 +89,52 @@
}
func withoutOptions() {
- self.container.backgroundColor = UIColor.clear
- self.backgroundBlurEffect.isHidden = true
- muteAudioButton.isHidden = true
- muteVideoButton.isHidden = true
- pauseCallButton.isHidden = true
- switchCameraButton.isHidden = true
- switchSpeakerButton.isHidden = true
- cancelButton.isHidden = false
+ self.container.backgroundColor = UIColor.clear
+ self.backgroundBlurEffect.isHidden = true
+ muteAudioButton.isHidden = true
+ muteVideoButton.isHidden = true
+ pauseCallButton.isHidden = true
+ switchCameraButton.isHidden = true
+ switchSpeakerButton.isHidden = true
+ cancelButton.isHidden = false
}
func optionsWithSpeaker() {
- self.backgroundBlurEffect.isHidden = false
- muteAudioButton.isHidden = false
- if self.viewModel?.isAudioOnly ?? false {
- self.stackViewWidthConstraint.constant = 200
- muteVideoButton.isHidden = true
- switchCameraButton.isHidden = true
- } else {
- muteVideoButton.isHidden = false
- switchCameraButton.isHidden = false
+ if !self.isCallStarted {
+ self.isCallStarted = true
+ self.backgroundBlurEffect.isHidden = false
+ muteAudioButton.isHidden = false
+ if self.viewModel?.isAudioOnly ?? false {
+ muteVideoButton.isHidden = true
+ switchCameraButton.isHidden = true
+ } else {
+ muteVideoButton.isHidden = false
+ switchCameraButton.isHidden = false
+ }
+ pauseCallButton.isHidden = false
+ switchSpeakerButton.isHidden = false
+ switchSpeakerButton.alpha = 1.00
+ switchSpeakerButton.isEnabled = true
+ cancelButton.isHidden = false
}
- pauseCallButton.isHidden = false
- switchSpeakerButton.isHidden = false
- switchSpeakerButton.alpha = 1.00
- switchSpeakerButton.isEnabled = true
- cancelButton.isHidden = false
}
func optionsWithoutSpeaker() {
- if self.viewModel?.isAudioOnly ?? false {
- self.stackViewWidthConstraint.constant = 150
- muteVideoButton.isHidden = true
- switchCameraButton.isHidden = true
- } else {
- muteVideoButton.isHidden = false
- switchCameraButton.isHidden = false
+ if !self.isCallStarted {
+ self.isCallStarted = true
+ if self.viewModel?.isAudioOnly ?? false {
+ muteVideoButton.isHidden = true
+ switchCameraButton.isHidden = true
+ switchSpeakerButton.isHidden = true
+ } else {
+ muteVideoButton.isHidden = false
+ switchCameraButton.isHidden = false
+ switchSpeakerButton.isHidden = false
+ }
+ self.muteAudioButton.isHidden = false
+ self.backgroundBlurEffect.isHidden = false
+ pauseCallButton.isHidden = false
+ cancelButton.isHidden = false
}
- self.backgroundBlurEffect.isHidden = false
- muteAudioButton.isHidden = false
- pauseCallButton.isHidden = false
- switchSpeakerButton.isHidden = true
- cancelButton.isHidden = false
}
}
diff --git a/Ring/Ring/Calls/ButtonsContainerView.xib b/Ring/Ring/Calls/ButtonsContainerView.xib
index c5e5662..a82e14d 100644
--- a/Ring/Ring/Calls/ButtonsContainerView.xib
+++ b/Ring/Ring/Calls/ButtonsContainerView.xib
@@ -14,39 +14,46 @@
<connections>
<outlet property="backgroundBlurEffect" destination="w5l-pw-1ET" id="YYh-qB-WIL"/>
<outlet property="cancelButton" destination="ZxT-mA-1xU" id="68q-sF-gBC"/>
- <outlet property="cancelButtonHeightConstraint" destination="XhM-wC-j2L" id="xcg-V6-2BW"/>
+ <outlet property="cancelButtonBottomConstraint" destination="Ilu-Zu-JqW" id="Yeg-Ca-8pf"/>
+ <outlet property="cancelButtonHeightConstraint" destination="kls-aA-2zS" id="CzE-vC-V5Z"/>
+ <outlet property="cancelButtonWidthConstraint" destination="0vV-4C-odp" id="beL-yR-ehA"/>
<outlet property="container" destination="a9g-pf-bHy" id="6bw-CB-5qN"/>
- <outlet property="containerHeightConstraint" destination="W6T-0D-HwX" id="Pdz-5B-x5j"/>
+ <outlet property="containerHeightConstraint" destination="Gjk-7U-rEe" id="G5G-Uh-zRV"/>
<outlet property="containerView" destination="iN0-l3-epB" id="mcP-kY-dVO"/>
<outlet property="muteAudioButton" destination="tXL-FB-O0X" id="6Bh-x3-veQ"/>
<outlet property="muteVideoButton" destination="W7F-nH-kda" id="MWK-JU-544"/>
<outlet property="pauseCallButton" destination="MPk-dB-dhR" id="W4G-AB-WFw"/>
<outlet property="stackView" destination="RHx-cL-CV5" id="Iz9-B0-2Rd"/>
- <outlet property="stackViewBottomConstraint" destination="deA-Gc-8FZ" id="etU-MD-0Ig"/>
- <outlet property="stackViewWidthConstraint" destination="mIk-2g-tbX" id="Wcy-wd-Quy"/>
+ <outlet property="stackViewWidthConstraint" destination="ZuV-LV-CYZ" id="ita-8Y-fAb"/>
+ <outlet property="stackViewYConstraint" destination="z8B-uv-Vcb" id="Gaj-8x-yif"/>
<outlet property="switchCameraButton" destination="gfb-nb-FyB" id="FTM-2Z-u3u"/>
<outlet property="switchSpeakerButton" destination="0VH-mO-vFE" id="1Gy-a9-FAW"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
- <rect key="frame" x="0.0" y="0.0" width="375" height="205"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="108"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a9g-pf-bHy">
- <rect key="frame" x="0.0" y="0.0" width="375" height="205"/>
+ <rect key="frame" x="0.0" y="-2" width="375" height="110"/>
<subviews>
- <visualEffectView opaque="NO" alpha="0.84999999999999998" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="w5l-pw-1ET" userLabel="Background Blur Effect">
- <rect key="frame" x="0.0" y="0.0" width="375" height="205"/>
+ <visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="w5l-pw-1ET" userLabel="Background Blur Effect">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="110"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="JSn-50-Cd9">
- <rect key="frame" x="0.0" y="0.0" width="375" height="205"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="110"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
- <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="calibratedWhite"/>
<blurEffect style="light"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
+ <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+ <real key="value" value="35"/>
+ </userDefinedRuntimeAttribute>
+ </userDefinedRuntimeAttributes>
</visualEffectView>
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="RHx-cL-CV5">
- <rect key="frame" x="12.5" y="5" width="350" height="50"/>
+ <rect key="frame" x="15" y="30" width="345" height="50"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tXL-FB-O0X">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
@@ -70,7 +77,7 @@
</userDefinedRuntimeAttributes>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="W7F-nH-kda">
- <rect key="frame" x="75" y="0.0" width="50" height="50"/>
+ <rect key="frame" x="74" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="Pn1-SS-vPN"/>
<constraint firstAttribute="width" constant="50" id="jCp-ib-ySo"/>
@@ -91,7 +98,7 @@
</userDefinedRuntimeAttributes>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0VH-mO-vFE">
- <rect key="frame" x="150" y="0.0" width="50" height="50"/>
+ <rect key="frame" x="147.5" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="oso-jU-2U3"/>
<constraint firstAttribute="height" constant="50" id="qmE-To-ipl"/>
@@ -112,7 +119,7 @@
</userDefinedRuntimeAttributes>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MPk-dB-dhR">
- <rect key="frame" x="225" y="0.0" width="50" height="50"/>
+ <rect key="frame" x="221.5" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="width" constant="50" id="984-Na-56G"/>
<constraint firstAttribute="height" constant="50" id="kIF-vP-ZJP"/>
@@ -133,7 +140,7 @@
</userDefinedRuntimeAttributes>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="gfb-nb-FyB">
- <rect key="frame" x="300" y="0.0" width="50" height="50"/>
+ <rect key="frame" x="295" y="0.0" width="50" height="50"/>
<constraints>
<constraint firstAttribute="height" constant="50" id="DYV-x7-KoO"/>
<constraint firstAttribute="width" constant="50" id="XYg-b8-pt8"/>
@@ -156,12 +163,12 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
+ <constraint firstAttribute="width" priority="250" constant="200" id="ZuV-LV-CYZ"/>
<constraint firstAttribute="height" constant="50" id="gaC-GZ-ftw"/>
- <constraint firstAttribute="width" constant="350" id="mIk-2g-tbX"/>
</constraints>
</stackView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZxT-mA-1xU">
- <rect key="frame" x="152.5" y="75" width="70" height="70"/>
+ <rect key="frame" x="152.5" y="20" width="70" height="70"/>
<constraints>
<constraint firstAttribute="width" constant="70" id="0vV-4C-odp"/>
<constraint firstAttribute="height" constant="70" id="kls-aA-2zS"/>
@@ -184,28 +191,29 @@
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="w5l-pw-1ET" firstAttribute="height" secondItem="a9g-pf-bHy" secondAttribute="height" id="3vF-Mr-YlI"/>
- <constraint firstItem="RHx-cL-CV5" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="a9g-pf-bHy" secondAttribute="leading" constant="12.5" id="FwG-sE-gpJ"/>
+ <constraint firstAttribute="height" constant="110" id="Gjk-7U-rEe"/>
+ <constraint firstAttribute="bottom" secondItem="ZxT-mA-1xU" secondAttribute="bottom" constant="20" id="Ilu-Zu-JqW"/>
<constraint firstItem="w5l-pw-1ET" firstAttribute="centerY" secondItem="a9g-pf-bHy" secondAttribute="centerY" id="Key-mX-9mY"/>
- <constraint firstAttribute="height" priority="999" constant="212" id="W6T-0D-HwX"/>
- <constraint firstAttribute="bottom" secondItem="ZxT-mA-1xU" secondAttribute="bottom" priority="250" constant="60" id="XhM-wC-j2L"/>
+ <constraint firstAttribute="trailing" secondItem="w5l-pw-1ET" secondAttribute="trailing" id="TnQ-lp-9B9"/>
+ <constraint firstItem="RHx-cL-CV5" firstAttribute="leading" secondItem="a9g-pf-bHy" secondAttribute="leading" constant="15" id="Y9c-4n-eid"/>
+ <constraint firstAttribute="width" relation="lessThanOrEqual" constant="450" id="ZfR-cx-MUB"/>
+ <constraint firstItem="w5l-pw-1ET" firstAttribute="leading" secondItem="a9g-pf-bHy" secondAttribute="leading" id="bbd-5D-5So"/>
<constraint firstItem="RHx-cL-CV5" firstAttribute="centerX" secondItem="a9g-pf-bHy" secondAttribute="centerX" id="bmE-qo-8aJ"/>
- <constraint firstAttribute="bottom" secondItem="RHx-cL-CV5" secondAttribute="bottom" constant="150" id="deA-Gc-8FZ"/>
- <constraint firstItem="w5l-pw-1ET" firstAttribute="centerX" secondItem="a9g-pf-bHy" secondAttribute="centerX" id="eH5-i0-6bS"/>
<constraint firstItem="ZxT-mA-1xU" firstAttribute="centerX" secondItem="a9g-pf-bHy" secondAttribute="centerX" id="eV9-Wr-xF9"/>
- <constraint firstItem="w5l-pw-1ET" firstAttribute="width" secondItem="a9g-pf-bHy" secondAttribute="width" id="sXZ-Jz-OmC"/>
+ <constraint firstAttribute="trailing" secondItem="RHx-cL-CV5" secondAttribute="trailing" constant="15" id="pgj-7m-5gr"/>
+ <constraint firstAttribute="bottom" secondItem="RHx-cL-CV5" secondAttribute="bottom" constant="30" id="z8B-uv-Vcb"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
- <constraint firstItem="a9g-pf-bHy" firstAttribute="height" secondItem="iN0-l3-epB" secondAttribute="height" id="Kgd-1N-Hij"/>
- <constraint firstItem="a9g-pf-bHy" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" id="X3f-ZS-P0M"/>
- <constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="a9g-pf-bHy" secondAttribute="bottom" id="svV-zg-XlK"/>
+ <constraint firstAttribute="bottom" secondItem="a9g-pf-bHy" secondAttribute="bottom" id="YHm-ET-yjX"/>
+ <constraint firstItem="a9g-pf-bHy" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" priority="750" id="ZI5-4F-WCS"/>
<constraint firstItem="a9g-pf-bHy" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="uv2-qL-KQX"/>
</constraints>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
- <point key="canvasLocation" x="32.799999999999997" y="68.815592203898049"/>
+ <point key="canvasLocation" x="32.799999999999997" y="111.54422788605699"/>
</view>
</objects>
<resources>
diff --git a/Ring/Ring/Calls/CallViewController.storyboard b/Ring/Ring/Calls/CallViewController.storyboard
index 2fe6c5c..3c73c46 100644
--- a/Ring/Ring/Calls/CallViewController.storyboard
+++ b/Ring/Ring/Calls/CallViewController.storyboard
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ngv-XP-7A7">
- <device id="retina4_7" orientation="landscape">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ngv-XP-7A7">
+ <device id="retina5_9" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
+ <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
@@ -13,26 +14,26 @@
<scene sceneID="XKD-ru-Nw9">
<objects>
<viewController title="Calls" id="ngv-XP-7A7" customClass="CallViewController" customModule="Ring" customModuleProvider="target" sceneMemberID="viewController">
- <layoutGuides>
- <viewControllerLayoutGuide type="top" id="WrD-XI-6aI"/>
- <viewControllerLayoutGuide type="bottom" id="4n1-G8-SAO"/>
- </layoutGuides>
<view key="view" contentMode="scaleAspectFill" id="QpJ-Sx-9dG">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZVy-nB-bKJ" userLabel="CallView">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="DMu-Or-dd7">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</imageView>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="K0W-KI-Ul4" userLabel="Before Incoming Video">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
+ <color key="backgroundColor" white="0.14999999999999999" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </view>
<view opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" translatesAutoresizingMaskIntoConstraints="NO" id="Zmp-OX-Cez" userLabel="Spinner View">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<subviews>
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" misplaced="YES" hidesWhenStopped="YES" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="nwA-ao-thv" userLabel="Spinner">
- <rect key="frame" x="158" y="303" width="37" height="37"/>
+ <rect key="frame" x="159" y="304" width="37" height="37"/>
<constraints>
<constraint firstAttribute="height" constant="60" id="L0P-eF-lwK"/>
<constraint firstAttribute="width" constant="60" id="WUu-r6-CgN"/>
@@ -46,21 +47,27 @@
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3RN-4M-qR4" userLabel="InformationContainer">
- <rect key="frame" x="0.0" y="0.0" width="667" height="210"/>
+ <rect key="frame" x="10" y="54" width="355" height="110"/>
<subviews>
- <visualEffectView opaque="NO" alpha="0.84999999999999998" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zuX-Zf-IN1" userLabel="Background Blur Effect">
- <rect key="frame" x="0.0" y="0.0" width="667" height="210"/>
+ <visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zuX-Zf-IN1" userLabel="Info Blur Effect">
+ <rect key="frame" x="0.0" y="0.0" width="355" height="110"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="5ij-xj-eeA">
- <rect key="frame" x="0.0" y="0.0" width="667" height="210"/>
+ <rect key="frame" x="0.0" y="0.0" width="355" height="110"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
</view>
<blurEffect style="light"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
+ <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+ <real key="value" value="35"/>
+ </userDefinedRuntimeAttribute>
+ </userDefinedRuntimeAttributes>
</visualEffectView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="z3c-S7-uGw">
- <rect key="frame" x="0.0" y="0.0" width="667" height="210"/>
+ <rect key="frame" x="15" y="0.0" width="355" height="110"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_contact_picture" translatesAutoresizingMaskIntoConstraints="NO" id="T4r-6x-bEH">
- <rect key="frame" x="20" y="60" width="80" height="80"/>
+ <rect key="frame" x="0.0" y="15" width="80" height="80"/>
<constraints>
<constraint firstAttribute="width" constant="80" id="0Y6-p4-ZmY"/>
<constraint firstAttribute="height" constant="80" id="6oh-7x-V80"/>
@@ -72,43 +79,44 @@
<userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
</userDefinedRuntimeAttributes>
</imageView>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fac-lR-4on">
- <rect key="frame" x="20" y="160" width="0.0" height="40"/>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cgd-Wa-clf">
+ <rect key="frame" x="90" y="43" width="0.0" height="0.0"/>
+ <fontDescription key="fontDescription" type="system" pointSize="23"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
+ <nil key="highlightedColor"/>
+ </label>
+ <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00:00" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fac-lR-4on">
+ <rect key="frame" x="90" y="47" width="55" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="40" id="uWM-mZ-BSi"/>
</constraints>
- <fontDescription key="fontDescription" type="system" pointSize="23"/>
- <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cgd-Wa-clf">
- <rect key="frame" x="110" y="105" width="0.0" height="0.0"/>
- <fontDescription key="fontDescription" type="system" pointSize="20"/>
- <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
- <nil key="highlightedColor"/>
+ <fontDescription key="fontDescription" type="system" weight="light" pointSize="20"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
+ <color key="highlightedColor" red="0.99999600649999998" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
- <constraint firstItem="fac-lR-4on" firstAttribute="leading" secondItem="T4r-6x-bEH" secondAttribute="leading" id="5S2-6O-mBj"/>
- <constraint firstItem="T4r-6x-bEH" firstAttribute="top" secondItem="z3c-S7-uGw" secondAttribute="top" constant="60" id="diz-IR-6aJ"/>
+ <constraint firstItem="T4r-6x-bEH" firstAttribute="centerY" secondItem="z3c-S7-uGw" secondAttribute="centerY" id="7u7-pq-Sco"/>
+ <constraint firstItem="fac-lR-4on" firstAttribute="leading" secondItem="T4r-6x-bEH" secondAttribute="trailing" constant="10" id="CB6-2m-9bA"/>
+ <constraint firstItem="T4r-6x-bEH" firstAttribute="leading" secondItem="z3c-S7-uGw" secondAttribute="leading" id="crx-6E-j4t"/>
<constraint firstItem="cgd-Wa-clf" firstAttribute="leading" secondItem="T4r-6x-bEH" secondAttribute="trailing" constant="10" id="f1b-Fu-RU9"/>
- <constraint firstItem="cgd-Wa-clf" firstAttribute="centerY" secondItem="z3c-S7-uGw" secondAttribute="centerY" id="hhM-ww-O86"/>
- <constraint firstAttribute="bottom" secondItem="fac-lR-4on" secondAttribute="bottom" constant="10" id="px3-II-ycz"/>
- <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="cgd-Wa-clf" secondAttribute="trailing" constant="10" id="sWn-1r-rwA"/>
- <constraint firstItem="T4r-6x-bEH" firstAttribute="leading" secondItem="z3c-S7-uGw" secondAttribute="leading" constant="20" id="uwm-g8-FeG"/>
+ <constraint firstItem="cgd-Wa-clf" firstAttribute="centerY" secondItem="z3c-S7-uGw" secondAttribute="centerY" constant="-12" id="hhM-ww-O86"/>
+ <constraint firstItem="fac-lR-4on" firstAttribute="centerY" secondItem="z3c-S7-uGw" secondAttribute="centerY" constant="12" id="nJi-4z-dfk"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="z3c-S7-uGw" firstAttribute="top" secondItem="3RN-4M-qR4" secondAttribute="top" id="5sX-gp-vmP"/>
+ <constraint firstItem="zuX-Zf-IN1" firstAttribute="leading" secondItem="3RN-4M-qR4" secondAttribute="leading" id="7Fo-ia-ZH9"/>
+ <constraint firstAttribute="trailing" secondItem="zuX-Zf-IN1" secondAttribute="trailing" id="C23-bJ-Z9C"/>
<constraint firstAttribute="bottom" secondItem="z3c-S7-uGw" secondAttribute="bottom" id="COe-Fm-vFD"/>
- <constraint firstItem="z3c-S7-uGw" firstAttribute="leading" secondItem="3RN-4M-qR4" secondAttribute="leading" id="Q0l-UK-zgA"/>
- <constraint firstAttribute="trailing" secondItem="z3c-S7-uGw" secondAttribute="trailing" id="YSf-ft-0uw"/>
- <constraint firstAttribute="height" constant="210" id="b8L-UJ-IKC"/>
+ <constraint firstAttribute="width" secondItem="z3c-S7-uGw" secondAttribute="width" id="GPS-Xu-Dh9"/>
+ <constraint firstAttribute="height" constant="110" id="b8L-UJ-IKC"/>
<constraint firstItem="zuX-Zf-IN1" firstAttribute="centerX" secondItem="3RN-4M-qR4" secondAttribute="centerX" id="dvv-WD-CHe"/>
<constraint firstItem="zuX-Zf-IN1" firstAttribute="height" secondItem="3RN-4M-qR4" secondAttribute="height" id="iOd-AE-0WJ"/>
- <constraint firstItem="zuX-Zf-IN1" firstAttribute="width" secondItem="3RN-4M-qR4" secondAttribute="width" id="uwm-HG-NEQ"/>
+ <constraint firstItem="z3c-S7-uGw" firstAttribute="leading" secondItem="3RN-4M-qR4" secondAttribute="leading" constant="15" id="rCU-BK-THY"/>
+ <constraint firstAttribute="width" relation="lessThanOrEqual" constant="450" id="s26-g3-GCZ"/>
<constraint firstItem="zuX-Zf-IN1" firstAttribute="centerY" secondItem="3RN-4M-qR4" secondAttribute="centerY" id="z97-Gw-2Mw"/>
</constraints>
<userDefinedRuntimeAttributes>
@@ -117,36 +125,64 @@
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
- <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CfE-DF-buX" userLabel="CapturedVideo">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
- </imageView>
+ <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZK1-Be-lcD" userLabel="ViewCapturedVideo">
+ <rect key="frame" x="0.0" y="-1" width="375" height="857"/>
+ <subviews>
+ <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="CfE-DF-buX" userLabel="CapturedVideo">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="857"/>
+ </imageView>
+ <visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rt7-JS-vjg" userLabel="Blur Effect">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="857"/>
+ <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="PYX-1b-sbf">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="857"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ </view>
+ <color key="backgroundColor" red="0.99999600649999998" green="1" blue="1" alpha="0.17999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
+ <blurEffect style="light"/>
+ </visualEffectView>
+ </subviews>
+ <constraints>
+ <constraint firstItem="CfE-DF-buX" firstAttribute="centerX" secondItem="ZK1-Be-lcD" secondAttribute="centerX" id="51a-aO-iap"/>
+ <constraint firstItem="CfE-DF-buX" firstAttribute="height" secondItem="ZK1-Be-lcD" secondAttribute="height" id="O6Q-I4-gU3"/>
+ <constraint firstItem="rt7-JS-vjg" firstAttribute="centerX" secondItem="CfE-DF-buX" secondAttribute="centerX" id="QPi-iO-gGH"/>
+ <constraint firstItem="rt7-JS-vjg" firstAttribute="width" secondItem="CfE-DF-buX" secondAttribute="width" id="VX9-wH-CfO"/>
+ <constraint firstItem="rt7-JS-vjg" firstAttribute="height" secondItem="CfE-DF-buX" secondAttribute="height" id="glm-Va-dTY"/>
+ <constraint firstItem="CfE-DF-buX" firstAttribute="centerY" secondItem="ZK1-Be-lcD" secondAttribute="centerY" id="pDf-fu-Le6"/>
+ <constraint firstItem="CfE-DF-buX" firstAttribute="width" secondItem="ZK1-Be-lcD" secondAttribute="width" id="r1F-if-HbN"/>
+ <constraint firstItem="rt7-JS-vjg" firstAttribute="centerY" secondItem="CfE-DF-buX" secondAttribute="centerY" id="tCB-hE-MJu"/>
+ </constraints>
+ </view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
+ <constraint firstItem="cgd-Wa-clf" firstAttribute="trailing" relation="lessThanOrEqual" secondItem="ZK1-Be-lcD" secondAttribute="leading" priority="999" constant="-7" id="1p9-dp-14p"/>
<constraint firstItem="DMu-Or-dd7" firstAttribute="centerX" secondItem="ZVy-nB-bKJ" secondAttribute="centerX" id="2Lu-4b-uBO"/>
- <constraint firstAttribute="trailing" secondItem="CfE-DF-buX" secondAttribute="trailing" id="2VP-Yx-tvc" userLabel="Captured Video Trailing Constraint"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="3RN-4M-qR4" secondAttribute="trailing" constant="10" identifier="InfoContainerTrailingConstraint" id="5V0-5o-h5c"/>
<constraint firstItem="Zmp-OX-Cez" firstAttribute="height" secondItem="DMu-Or-dd7" secondAttribute="height" id="6ZM-UX-wEQ"/>
- <constraint firstItem="3RN-4M-qR4" firstAttribute="top" secondItem="ZVy-nB-bKJ" secondAttribute="top" id="72y-vN-PbI"/>
<constraint firstItem="DMu-Or-dd7" firstAttribute="width" secondItem="ZVy-nB-bKJ" secondAttribute="width" id="9tF-Ne-Pxj"/>
- <constraint firstItem="CfE-DF-buX" firstAttribute="top" secondItem="ZVy-nB-bKJ" secondAttribute="top" id="C3M-e1-UxG"/>
- <constraint firstItem="3RN-4M-qR4" firstAttribute="leading" secondItem="ZVy-nB-bKJ" secondAttribute="leading" id="CTU-NV-fjk"/>
<constraint firstItem="Zmp-OX-Cez" firstAttribute="width" secondItem="DMu-Or-dd7" secondAttribute="width" id="HHk-TU-w9h"/>
- <constraint firstAttribute="trailing" secondItem="3RN-4M-qR4" secondAttribute="trailing" id="IFT-I3-DEM"/>
- <constraint firstItem="CfE-DF-buX" firstAttribute="width" secondItem="ZVy-nB-bKJ" secondAttribute="width" id="KQc-xt-KPb"/>
+ <constraint firstItem="3RN-4M-qR4" firstAttribute="centerX" secondItem="ZVy-nB-bKJ" secondAttribute="centerX" id="PNs-gW-YZp"/>
<constraint firstItem="DMu-Or-dd7" firstAttribute="height" secondItem="ZVy-nB-bKJ" secondAttribute="height" id="Xd0-GB-gSC"/>
- <constraint firstItem="CfE-DF-buX" firstAttribute="height" secondItem="ZVy-nB-bKJ" secondAttribute="height" id="Zun-HA-2Id"/>
+ <constraint firstItem="K0W-KI-Ul4" firstAttribute="width" secondItem="DMu-Or-dd7" secondAttribute="width" id="ZZ0-hX-Nwm"/>
+ <constraint firstItem="ZK1-Be-lcD" firstAttribute="height" secondItem="ZVy-nB-bKJ" secondAttribute="height" constant="45" id="Zyu-M5-fjh"/>
+ <constraint firstItem="K0W-KI-Ul4" firstAttribute="centerY" secondItem="DMu-Or-dd7" secondAttribute="centerY" id="cTk-Hv-nxM"/>
<constraint firstItem="Zmp-OX-Cez" firstAttribute="centerX" secondItem="DMu-Or-dd7" secondAttribute="centerX" id="f1S-rO-Hld"/>
+ <constraint firstItem="K0W-KI-Ul4" firstAttribute="height" secondItem="DMu-Or-dd7" secondAttribute="height" id="grY-ie-rVw"/>
+ <constraint firstItem="K0W-KI-Ul4" firstAttribute="centerX" secondItem="DMu-Or-dd7" secondAttribute="centerX" id="oCc-Yp-7Ay"/>
+ <constraint firstItem="ZK1-Be-lcD" firstAttribute="width" secondItem="ZVy-nB-bKJ" secondAttribute="width" id="uTd-rs-MJH"/>
+ <constraint firstAttribute="trailing" secondItem="ZK1-Be-lcD" secondAttribute="trailing" id="ugJ-SF-Enn"/>
+ <constraint firstItem="3RN-4M-qR4" firstAttribute="width" relation="greaterThanOrEqual" secondItem="ZVy-nB-bKJ" secondAttribute="width" priority="999" id="vfb-7h-8HZ"/>
<constraint firstItem="Zmp-OX-Cez" firstAttribute="centerY" secondItem="DMu-Or-dd7" secondAttribute="centerY" id="vuz-oT-1VO"/>
<constraint firstItem="DMu-Or-dd7" firstAttribute="centerY" secondItem="ZVy-nB-bKJ" secondAttribute="centerY" id="yFh-zq-lXh"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5E0-lB-SkS" userLabel="AvatarView">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<subviews>
- <visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uC8-vY-dHO">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <visualEffectView opaque="NO" alpha="0.0" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uC8-vY-dHO">
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="cOr-ft-BIO">
- <rect key="frame" x="0.0" y="0.0" width="667" height="375"/>
+ <rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
@@ -154,11 +190,11 @@
<blurEffect style="light"/>
</visualEffectView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Dj8-CK-PQm" userLabel="Call Pulse">
- <rect key="frame" x="258.5" y="-37.5" width="150" height="150"/>
+ <rect key="frame" x="112.66666666666669" y="120" width="150" height="150"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_contact_picture" translatesAutoresizingMaskIntoConstraints="NO" id="fnt-PQ-Q6P">
- <rect key="frame" x="258.5" y="-37.5" width="150" height="150"/>
+ <rect key="frame" x="112.66666666666669" y="120" width="150" height="150"/>
<constraints>
<constraint firstAttribute="width" constant="150" id="Miw-Nd-4Fa"/>
<constraint firstAttribute="height" constant="150" id="V9c-7W-Frv"/>
@@ -172,95 +208,107 @@
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="73Y-N1-Yga">
<rect key="frame" x="187" y="333" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
- <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zMN-6z-uXT">
<rect key="frame" x="187" y="333" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="20"/>
- <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SdV-jx-Mla">
<rect key="frame" x="187" y="333" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="20"/>
- <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+ <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="uC8-vY-dHO" firstAttribute="centerY" secondItem="5E0-lB-SkS" secondAttribute="centerY" id="4Mf-hA-tZO"/>
+ <constraint firstItem="fnt-PQ-Q6P" firstAttribute="top" secondItem="5E0-lB-SkS" secondAttribute="top" constant="120" id="82d-fj-m0F"/>
<constraint firstItem="Dj8-CK-PQm" firstAttribute="width" secondItem="fnt-PQ-Q6P" secondAttribute="width" id="CUd-sE-c9g"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="73Y-N1-Yga" secondAttribute="trailing" constant="20" id="E64-Eo-ffn"/>
<constraint firstItem="73Y-N1-Yga" firstAttribute="bottom" secondItem="fnt-PQ-Q6P" secondAttribute="bottom" constant="45" id="ExS-S7-RrD"/>
<constraint firstItem="73Y-N1-Yga" firstAttribute="centerX" secondItem="fnt-PQ-Q6P" secondAttribute="centerX" id="HBR-dG-PgV"/>
<constraint firstItem="Dj8-CK-PQm" firstAttribute="height" secondItem="fnt-PQ-Q6P" secondAttribute="height" id="JQ8-d6-nUa"/>
<constraint firstItem="fnt-PQ-Q6P" firstAttribute="centerX" secondItem="5E0-lB-SkS" secondAttribute="centerX" id="Me2-uR-EQh"/>
<constraint firstItem="uC8-vY-dHO" firstAttribute="centerX" secondItem="5E0-lB-SkS" secondAttribute="centerX" id="TJC-Hb-JIm"/>
<constraint firstItem="Dj8-CK-PQm" firstAttribute="top" secondItem="fnt-PQ-Q6P" secondAttribute="top" id="W5C-IT-OVb"/>
- <constraint firstItem="fnt-PQ-Q6P" firstAttribute="centerY" secondItem="5E0-lB-SkS" secondAttribute="centerY" constant="-150" id="cGj-TY-G3p"/>
<constraint firstItem="zMN-6z-uXT" firstAttribute="bottom" secondItem="fnt-PQ-Q6P" secondAttribute="bottom" constant="80" id="ecZ-zH-cYs"/>
<constraint firstItem="uC8-vY-dHO" firstAttribute="height" secondItem="5E0-lB-SkS" secondAttribute="height" id="hfH-qy-12N"/>
<constraint firstItem="Dj8-CK-PQm" firstAttribute="centerX" secondItem="5E0-lB-SkS" secondAttribute="centerX" id="izi-2p-nAy"/>
<constraint firstItem="uC8-vY-dHO" firstAttribute="width" secondItem="5E0-lB-SkS" secondAttribute="width" id="pAd-aZ-0Mj"/>
<constraint firstItem="zMN-6z-uXT" firstAttribute="centerX" secondItem="fnt-PQ-Q6P" secondAttribute="centerX" id="w8O-3h-Axl"/>
+ <constraint firstItem="73Y-N1-Yga" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="5E0-lB-SkS" secondAttribute="leading" constant="20" id="yRj-S6-9PE"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LK6-u0-eLU" customClass="ButtonsContainerView" customModule="Ring" customModuleProvider="target">
- <rect key="frame" x="0.0" y="175" width="667" height="200"/>
+ <rect key="frame" x="10" y="658" width="355" height="110"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
- <constraint firstAttribute="height" constant="200" id="r58-OO-QqE"/>
+ <constraint firstAttribute="height" constant="110" id="r58-OO-QqE"/>
</constraints>
</view>
</subviews>
<constraints>
- <constraint firstItem="LK6-u0-eLU" firstAttribute="leading" secondItem="QpJ-Sx-9dG" secondAttribute="leading" id="0oL-jv-UVj"/>
+ <constraint firstItem="LK6-u0-eLU" firstAttribute="leading" secondItem="lZI-X0-bkP" secondAttribute="leading" constant="10" id="0oL-jv-UVj"/>
<constraint firstItem="5E0-lB-SkS" firstAttribute="top" secondItem="ZVy-nB-bKJ" secondAttribute="top" id="1PH-hE-Wgj"/>
- <constraint firstItem="5E0-lB-SkS" firstAttribute="centerX" secondItem="LK6-u0-eLU" secondAttribute="centerX" id="6rQ-2e-IMs"/>
+ <constraint firstItem="LK6-u0-eLU" firstAttribute="centerX" secondItem="QpJ-Sx-9dG" secondAttribute="centerX" id="78D-th-J1t"/>
<constraint firstItem="ZVy-nB-bKJ" firstAttribute="height" secondItem="QpJ-Sx-9dG" secondAttribute="height" id="DB0-aS-tKo"/>
+ <constraint firstItem="3RN-4M-qR4" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="ZVy-nB-bKJ" secondAttribute="leading" constant="10" id="ElV-U4-tpk"/>
+ <constraint firstItem="SdV-jx-Mla" firstAttribute="centerX" secondItem="lZI-X0-bkP" secondAttribute="centerX" id="FMZ-tv-l27"/>
+ <constraint firstItem="lZI-X0-bkP" firstAttribute="top" secondItem="3RN-4M-qR4" secondAttribute="top" constant="-10" id="G1C-hv-89U"/>
+ <constraint firstItem="5E0-lB-SkS" firstAttribute="centerX" secondItem="lZI-X0-bkP" secondAttribute="centerX" id="INh-Ix-uWw"/>
<constraint firstItem="5E0-lB-SkS" firstAttribute="height" secondItem="QpJ-Sx-9dG" secondAttribute="height" id="KFS-O1-Acs"/>
<constraint firstItem="ZVy-nB-bKJ" firstAttribute="top" secondItem="QpJ-Sx-9dG" secondAttribute="top" id="NrK-DR-BPG"/>
- <constraint firstItem="SdV-jx-Mla" firstAttribute="bottom" secondItem="LK6-u0-eLU" secondAttribute="top" constant="60" id="YIc-Oj-lc8"/>
+ <constraint firstItem="lZI-X0-bkP" firstAttribute="top" secondItem="ZK1-Be-lcD" secondAttribute="top" constant="45" id="Uew-ao-q8k"/>
+ <constraint firstItem="SdV-jx-Mla" firstAttribute="bottom" secondItem="LK6-u0-eLU" secondAttribute="top" id="YIc-Oj-lc8"/>
<constraint firstItem="ZVy-nB-bKJ" firstAttribute="centerY" secondItem="QpJ-Sx-9dG" secondAttribute="centerY" id="bAN-gX-nPE"/>
- <constraint firstItem="SdV-jx-Mla" firstAttribute="centerX" secondItem="LK6-u0-eLU" secondAttribute="centerX" id="bET-0c-03Z"/>
- <constraint firstAttribute="trailing" secondItem="LK6-u0-eLU" secondAttribute="trailing" id="cl9-Fw-bSb"/>
- <constraint firstItem="4n1-G8-SAO" firstAttribute="top" secondItem="LK6-u0-eLU" secondAttribute="bottom" id="ePh-KL-t0K"/>
- <constraint firstItem="ZVy-nB-bKJ" firstAttribute="centerX" secondItem="QpJ-Sx-9dG" secondAttribute="centerX" id="ff0-Nw-f2Y"/>
+ <constraint firstItem="lZI-X0-bkP" firstAttribute="trailing" secondItem="LK6-u0-eLU" secondAttribute="trailing" constant="10" id="cl9-Fw-bSb"/>
+ <constraint firstItem="ZVy-nB-bKJ" firstAttribute="centerX" secondItem="lZI-X0-bkP" secondAttribute="centerX" id="ff0-Nw-f2Y"/>
+ <constraint firstItem="lZI-X0-bkP" firstAttribute="bottom" secondItem="LK6-u0-eLU" secondAttribute="bottom" constant="10" id="pFx-Iv-rIz"/>
<constraint firstItem="5E0-lB-SkS" firstAttribute="width" secondItem="QpJ-Sx-9dG" secondAttribute="width" id="rOQ-In-yON"/>
<constraint firstItem="ZVy-nB-bKJ" firstAttribute="width" secondItem="QpJ-Sx-9dG" secondAttribute="width" id="sCh-Gw-iu0"/>
</constraints>
+ <viewLayoutGuide key="safeArea" id="lZI-X0-bkP"/>
</view>
<nil key="simulatedBottomBarMetrics"/>
<connections>
+ <outlet property="ButtonsContainerBottomConstraint" destination="pFx-Iv-rIz" id="a4k-7r-1l0"/>
<outlet property="avatarView" destination="5E0-lB-SkS" id="zDj-oM-twh"/>
- <outlet property="backgroundBlurEffectHeightConstraint" destination="iOd-AE-0WJ" id="c3b-zR-no8"/>
+ <outlet property="avatarViewBlurEffect" destination="uC8-vY-dHO" id="lJD-lK-7CI"/>
+ <outlet property="avatarViewImageTopConstraint" destination="82d-fj-m0F" id="z3A-J5-tFD"/>
+ <outlet property="beforeIncomingVideo" destination="K0W-KI-Ul4" id="qrt-Kd-7S8"/>
+ <outlet property="buttonContainerHeightConstraint" destination="r58-OO-QqE" id="6Sg-fe-0ww"/>
<outlet property="buttonsContainer" destination="LK6-u0-eLU" id="rb7-9y-4Eh"/>
- <outlet property="buttonsContainerHeightConstraint" destination="r58-OO-QqE" id="VQ8-EZ-fCe"/>
+ <outlet property="buttonsContainerBottomConstraint" destination="pFx-Iv-rIz" id="83E-wF-mPF"/>
<outlet property="callInfoTimerLabel" destination="fac-lR-4on" id="fMl-JM-d9Y"/>
- <outlet property="callInfoTimerLabelBottomConstraint" destination="px3-II-ycz" id="fFg-W4-WlX"/>
- <outlet property="callInfoTimerLabelLeadingConstraint" destination="5S2-6O-mBj" id="XGw-tb-JrJ"/>
<outlet property="callNameLabel" destination="cgd-Wa-clf" id="oEa-7j-Eac"/>
<outlet property="callProfileImage" destination="T4r-6x-bEH" id="Pi5-eB-Eve"/>
- <outlet property="callProfileImageTopConstraint" destination="diz-IR-6aJ" id="fhW-FR-i20"/>
<outlet property="callPulse" destination="Dj8-CK-PQm" id="9e6-JQ-U6k"/>
<outlet property="callView" destination="ZVy-nB-bKJ" id="Sah-TI-SVz"/>
<outlet property="capturedVideo" destination="CfE-DF-buX" id="Hm5-ya-ijN"/>
- <outlet property="capturedVideoHeightConstraint" destination="Zun-HA-2Id" id="Iph-wQ-ddN"/>
- <outlet property="capturedVideoTopConstraint" destination="C3M-e1-UxG" id="cuz-sW-Jo5"/>
- <outlet property="capturedVideoTrailingConstraint" destination="2VP-Yx-tvc" id="87S-pf-IpY"/>
- <outlet property="capturedVideoWidthConstraint" destination="KQc-xt-KPb" id="h7P-ua-tw2"/>
+ <outlet property="capturedVideoBlurEffect" destination="rt7-JS-vjg" id="Swb-Mg-nfK"/>
+ <outlet property="capturedVideoHeightConstraint" destination="Zyu-M5-fjh" id="8c1-Us-gvl"/>
+ <outlet property="capturedVideoTopConstraint" destination="Uew-ao-q8k" id="tzK-s5-FwX"/>
+ <outlet property="capturedVideoTrailingConstraint" destination="ugJ-SF-Enn" id="Xlm-dP-U9Y"/>
+ <outlet property="capturedVideoWidthConstraint" destination="uTd-rs-MJH" id="4Fc-ot-W4i"/>
<outlet property="durationLabel" destination="zMN-6z-uXT" id="Uuf-ph-lrC"/>
<outlet property="incomingVideo" destination="DMu-Or-dd7" id="ogh-ft-54u"/>
+ <outlet property="infoBlurEffect" destination="zuX-Zf-IN1" id="hAl-Rg-hPM"/>
<outlet property="infoBottomLabel" destination="SdV-jx-Mla" id="yX9-em-p4w"/>
<outlet property="infoContainer" destination="3RN-4M-qR4" id="CUO-h6-mFf"/>
- <outlet property="infoContainerHeightConstraint" destination="b8L-UJ-IKC" id="HLq-aF-vqZ"/>
- <outlet property="infoLabelHeightConstraint" destination="YIc-Oj-lc8" id="8hk-Ig-bUC"/>
+ <outlet property="infoContainerHeightConstraint" destination="b8L-UJ-IKC" id="U6k-oI-MPH"/>
+ <outlet property="infoContainerTopConstraint" destination="G1C-hv-89U" id="MFr-jm-kBk"/>
<outlet property="mainView" destination="QpJ-Sx-9dG" id="0y9-R4-q5W"/>
<outlet property="nameLabel" destination="73Y-N1-Yga" id="XcQ-V6-ZrF"/>
- <outlet property="nameLabelYConstraint" destination="hhM-ww-O86" id="1fJ-Yh-MRW"/>
<outlet property="profileImageView" destination="fnt-PQ-Q6P" id="MgB-Ev-bTc"/>
+ <outlet property="profileImageViewHeightConstraint" destination="V9c-7W-Frv" id="0iC-TD-RuH"/>
+ <outlet property="profileImageViewWidthConstraint" destination="Miw-Nd-4Fa" id="OSp-7J-TGC"/>
<outlet property="spinner" destination="nwA-ao-thv" id="bJo-Wq-QmV"/>
+ <outlet property="viewCapturedVideo" destination="ZK1-Be-lcD" id="Go0-ab-yLg"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="OFk-0u-Pap" userLabel="First Responder" sceneMemberID="firstResponder"/>
diff --git a/Ring/Ring/Calls/CallViewController.swift b/Ring/Ring/Calls/CallViewController.swift
index 37660fd..8c89ab8 100644
--- a/Ring/Ring/Calls/CallViewController.swift
+++ b/Ring/Ring/Calls/CallViewController.swift
@@ -30,38 +30,46 @@
//preview screen
@IBOutlet private weak var profileImageView: UIImageView!
@IBOutlet private weak var nameLabel: UILabel!
- @IBOutlet weak var nameLabelYConstraint: NSLayoutConstraint!
@IBOutlet private weak var durationLabel: UILabel!
@IBOutlet private weak var infoBottomLabel: UILabel!
@IBOutlet weak var avatarView: UIView!
+ @IBOutlet weak var avatarViewBlurEffect: UIVisualEffectView!
+ @IBOutlet private weak var callPulse: UIView!
@IBOutlet private weak var mainView: UIView!
//video screen
@IBOutlet private weak var callView: UIView!
@IBOutlet private weak var incomingVideo: UIImageView!
+ @IBOutlet weak var beforeIncomingVideo: UIView!
@IBOutlet weak var spinner: UIActivityIndicatorView!
@IBOutlet weak var capturedVideo: UIImageView!
+ @IBOutlet weak var capturedVideoBlurEffect: UIVisualEffectView!
+ @IBOutlet weak var viewCapturedVideo: UIView!
+ @IBOutlet private weak var infoContainer: UIView!
+ @IBOutlet private weak var callProfileImage: UIImageView!
+ @IBOutlet private weak var callNameLabel: UILabel!
+ @IBOutlet private weak var callInfoTimerLabel: UILabel!
+ @IBOutlet private weak var buttonsContainer: ButtonsContainerView!
+ @IBOutlet weak var infoBlurEffect: UIVisualEffectView!
+
+ //Constraints
@IBOutlet weak var capturedVideoWidthConstraint: NSLayoutConstraint!
@IBOutlet weak var capturedVideoTrailingConstraint: NSLayoutConstraint!
@IBOutlet weak var capturedVideoTopConstraint: NSLayoutConstraint!
@IBOutlet weak var capturedVideoHeightConstraint: NSLayoutConstraint!
- @IBOutlet private weak var infoContainer: UIView!
+ @IBOutlet weak var infoContainerTopConstraint: NSLayoutConstraint!
+ @IBOutlet weak var buttonsContainerBottomConstraint: NSLayoutConstraint!
@IBOutlet weak var infoContainerHeightConstraint: NSLayoutConstraint!
- @IBOutlet private weak var callProfileImage: UIImageView!
- @IBOutlet weak var callProfileImageTopConstraint: NSLayoutConstraint!
- @IBOutlet private weak var callNameLabel: UILabel!
- @IBOutlet private weak var callInfoTimerLabel: UILabel!
- @IBOutlet weak var callInfoTimerLabelLeadingConstraint: NSLayoutConstraint!
- @IBOutlet weak var callInfoTimerLabelBottomConstraint: NSLayoutConstraint!
- @IBOutlet private weak var infoLabelHeightConstraint: NSLayoutConstraint!
- @IBOutlet private weak var callPulse: UIView!
+ @IBOutlet weak var buttonContainerHeightConstraint: NSLayoutConstraint!
+ @IBOutlet weak var avatarViewImageTopConstraint: NSLayoutConstraint!
+ @IBOutlet weak var profileImageViewWidthConstraint: NSLayoutConstraint!
+ @IBOutlet weak var profileImageViewHeightConstraint: NSLayoutConstraint!
- @IBOutlet private weak var buttonsContainer: ButtonsContainerView!
- @IBOutlet weak var buttonsContainerHeightConstraint: NSLayoutConstraint!
- @IBOutlet weak var backgroundBlurEffectHeightConstraint: NSLayoutConstraint!
var viewModel: CallViewModel!
+ var isCallStarted: Bool = false
+ var orientation = UIDevice.current.orientation
fileprivate let disposeBag = DisposeBag()
@@ -73,7 +81,7 @@
override func viewDidLoad() {
super.viewDidLoad()
- self.setColorButtons()
+ self.setAvatarView(true)
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(screenTapped))
self.mainView.addGestureRecognizer(tapGestureRecognizer)
self.setUpCallButtons()
@@ -85,11 +93,8 @@
if !self.avatarView.isHidden {
self.capturedVideoWidthConstraint.constant += 200
self.capturedVideoTrailingConstraint.constant = (self.capturedVideoWidthConstraint.constant - UIScreen.main.bounds.width) / 2
- self.infoLabelHeightConstraint.constant = 90
}
- default :
- //On other devices, we don't have notch, so the infoContainerHeightConstraint should be smaller
- self.infoContainerHeightConstraint.constant = 204
+ default : break
}
if self.viewModel.isAudioOnly {
// The durationLabel and buttonsContainer alpha is set here to 0, and to 1 (with a duration) when appear on the screen to have a fade in animation
@@ -98,6 +103,7 @@
self.showAllInfo()
self.setWhiteAvatarView()
} else {
+ //The status bar should be white for video calls and black for audio calls
UIApplication.shared.statusBarStyle = .lightContent
}
@@ -106,22 +112,6 @@
initCallAnimation()
}
- func setColorButtons() {
- if !(self.viewModel.call?.isAudioOnly ?? false) {
- self.buttonsContainer.cancelButton.backgroundColor = UIColor.white
- self.buttonsContainer.muteAudioButton.tintColor = UIColor.white
- self.buttonsContainer.muteAudioButton.borderColor = UIColor.white
- self.buttonsContainer.muteVideoButton.tintColor = UIColor.white
- self.buttonsContainer.muteVideoButton.borderColor = UIColor.white
- self.buttonsContainer.pauseCallButton.tintColor = UIColor.white
- self.buttonsContainer.pauseCallButton.borderColor = UIColor.white
- self.buttonsContainer.switchCameraButton.tintColor = UIColor.white
- self.buttonsContainer.switchCameraButton.borderColor = UIColor.white
- self.buttonsContainer.switchSpeakerButton.tintColor = UIColor.white
- self.buttonsContainer.switchSpeakerButton.borderColor = UIColor.white
- }
- }
-
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
@@ -130,9 +120,6 @@
UIApplication.shared.statusBarStyle = .default
self.callPulse.backgroundColor = UIColor.ringCallPulse
self.avatarView.backgroundColor = UIColor.white
- self.nameLabel.textColor = UIColor.ringCallInfos
- self.durationLabel.textColor = UIColor.ringCallInfos
- self.infoBottomLabel.textColor = UIColor.ringCallInfos
}
func initCallAnimation() {
@@ -157,8 +144,6 @@
func setUpCallButtons() {
self.buttonsContainer.viewModel = self.viewModel.containerViewModel
- self.buttonsContainerHeightConstraint.constant = self.buttonsContainer.containerHeightConstraint.constant
- //bind actions
self.buttonsContainer.cancelButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.removeFromScreen()
@@ -257,11 +242,17 @@
self.viewModel.callDuration.asObservable().observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] _ in
- if self?.durationLabel.text == "00:00:00" {
- UIView.animate(withDuration: 0.3, animations: {
- self?.durationLabel.alpha = 1
- self?.buttonsContainer.stackView.alpha = 1
- })
+ if self?.durationLabel.text != "" {
+ if (self?.viewModel.isAudioOnly)! {
+ self?.buttonContainerHeightConstraint.constant = 200
+ self?.buttonsContainer.containerHeightConstraint.constant = 200
+ self?.buttonsContainer.stackViewYConstraint.constant = 110
+ self?.buttonsContainer.stackViewWidthConstraint.priority = UILayoutPriority(rawValue: 999)
+ UIView.animate(withDuration: 0.3, animations: {
+ self?.durationLabel.alpha = 1
+ self?.buttonsContainer.stackView.alpha = 1
+ })
+ }
}
}).disposed(by: self.disposeBag)
@@ -278,6 +269,13 @@
.subscribe(onNext: { [weak self] frame in
if let image = frame {
self?.spinner.stopAnimating()
+ if self?.beforeIncomingVideo.alpha != 0 {
+ UIView.animate(withDuration: 0.4, animations: {
+ self?.beforeIncomingVideo.alpha = 0
+ }, completion: { [weak self] _ in
+ self?.beforeIncomingVideo.isHidden = true
+ })
+ }
DispatchQueue.main.async {
self?.incomingVideo.image = image
}
@@ -311,7 +309,7 @@
}).disposed(by: self.disposeBag)
if !self.viewModel.isAudioOnly {
- self.setupShowCapturedFrame()
+ self.resizeCapturedFrame()
}
self.viewModel.videoMuted
@@ -322,9 +320,9 @@
if !self.viewModel.isAudioOnly {
self.viewModel.callPaused
.observeOn(MainScheduler.instance)
- .map({value in return !value })
- .bind(to: self.avatarView.rx.isHidden)
- .disposed(by: self.disposeBag)
+ .subscribe(onNext: { show in
+ self.setAvatarView(show)
+ }).disposed(by: self.disposeBag)
}
self.viewModel.callPaused
@@ -337,33 +335,77 @@
}).disposed(by: self.disposeBag)
}
- func setupShowCapturedFrame() {
+ func setAvatarView(_ show: Bool) {
+ if !show {
+ self.avatarView.isHidden = true
+ } else {
+ if UIDevice.current.userInterfaceIdiom == .pad {
+ self.avatarViewImageTopConstraint.constant = 200
+ self.avatarView.isHidden = false
+ return
+ }
+ if self.orientation == .landscapeRight
+ || self.orientation == .landscapeLeft {
+ let device = UIDevice.modelName
+ if device == "iPhone 5" || device == "iPhone 5c" || device == "iPhone 5s" || device == "iPhone SE" {
+ self.profileImageViewWidthConstraint.constant = 90
+ self.profileImageViewHeightConstraint.constant = 90
+ self.profileImageView.cornerRadius = 45
+ }
+ if self.viewModel.isAudioOnly {
+ if device == "iPhone 5" || device == "iPhone 5c" || device == "iPhone 5s" || device == "iPhone SE" {
+ self.durationLabel.isHidden = true
+ }
+ self.buttonsContainer.backgroundBlurEffect.alpha = 0
+ self.profileImageViewWidthConstraint.constant = 90
+ self.profileImageViewHeightConstraint.constant = 90
+ self.profileImageView.cornerRadius = 45
+ }
+ if self.viewModel.call?.state == .ringing || self.viewModel.call?.state == .connecting {
+ self.avatarViewImageTopConstraint.constant = 20
+ } else {
+ self.avatarViewImageTopConstraint.constant = 10
+ }
+ if UIDevice.current.hasNotch {
+ self.buttonsContainerBottomConstraint.constant = 0
+ } else {
+ self.buttonsContainerBottomConstraint.constant = 10
+ }
+ } else {
+ if UIDevice.current.hasNotch {
+ self.avatarViewImageTopConstraint.constant = 120
+ } else {
+ self.avatarViewImageTopConstraint.constant = 85
+ }
+ self.buttonsContainerBottomConstraint.constant = 10
+ }
+ self.avatarView.isHidden = false
+ }
+ }
+
+ func resizeCapturedFrame() {
self.viewModel.showCapturedFrame
.observeOn(MainScheduler.instance)
.subscribe(onNext: { dontShow in
- if dontShow {
- self.showAllInfo()
- DispatchQueue.global(qos: .background).async {
- sleep(3)
- DispatchQueue.main.async {
- self.hideContactInfo()
- self.hideCancelButton()
- }
+ if dontShow && !self.isCallStarted {
+ self.isCallStarted = true
+ self.hideCancelButton()
+ let device = UIDevice.modelName
+ //Reduce the cancel button for small iPhone
+ switch device {
+ case "iPhone 5", "iPhone 5c", "iPhone 5s", "iPhone SE" :
+ self.buttonsContainer.cancelButtonWidthConstraint.constant = 50
+ self.buttonsContainer.cancelButtonHeightConstraint.constant = 50
+ self.buttonsContainer.cancelButton.cornerRadius = 25
+ self.buttonsContainer.cancelButtonBottomConstraint.constant = 30
+ default : break
}
UIView.animate(withDuration: 0.4, animations: { [unowned self] in
- let device = UIDevice.modelName
- switch device {
- case "iPhone X", "iPhone XS", "iPhone XS Max", "iPhone XR" :
- self.capturedVideoTopConstraint.constant = 40
- default :
- self.capturedVideoTopConstraint.constant = 32
- }
- self.capturedVideoTrailingConstraint.constant = 10
- self.capturedVideoWidthConstraint.constant = -UIScreen.main.bounds.width + 120
- self.capturedVideoHeightConstraint.constant = -UIScreen.main.bounds.height + 160
- self.capturedVideo.cornerRadius = 10
- self.view.layoutIfNeeded()
+ self.resizeCapturedVideo(withInfoContainer: false)
+ self.capturedVideoBlurEffect.alpha = 0
+ self.view.layoutIfNeeded()
}, completion: nil)
+ self.avatarViewBlurEffect.alpha = CGFloat(1)
}
}).disposed(by: self.disposeBag)
}
@@ -374,7 +416,9 @@
}
@objc func screenTapped() {
- self.viewModel.respondOnTap()
+ if self.avatarView.isHidden{
+ self.viewModel.respondOnTap()
+ }
}
func showCancelButton() {
@@ -383,6 +427,8 @@
}
func hideCancelButton() {
+ self.buttonsContainerBottomConstraint.constant = -150
+ self.infoContainerTopConstraint.constant = 150
self.buttonsContainer.isHidden = true
self.view.layoutIfNeeded()
}
@@ -392,6 +438,80 @@
self.view.layoutIfNeeded()
}
+ override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
+ // Waiting for screen size change
+ DispatchQueue.global(qos: .background).async {
+ sleep(UInt32(0.5))
+ DispatchQueue.main.async {
+ self.resizeCapturedVideo(withInfoContainer: !self.infoContainer.isHidden)
+ if UIDevice.current.hasNotch && (UIDevice.current.orientation == .landscapeRight || UIDevice.current.orientation == .landscapeLeft) && self.infoContainer.isHidden == false {
+ self.buttonsContainerBottomConstraint.constant = 1
+ }
+ }
+ }
+ self.viewModel.setCameraOrientation(orientation: UIDevice.current.orientation)
+ super.viewWillTransition(to: size, with: coordinator)
+ }
+
+ func resizeCapturedVideo(withInfoContainer: Bool) {
+ //Don't change anything if the orientation change to portraitUpsideDown, faceUp or faceDown
+ if UIDevice.current.orientation.rawValue != 5 && UIDevice.current.orientation.rawValue != 6 && UIDevice.current.orientation.rawValue != 2 {
+ self.orientation = UIDevice.current.orientation
+ }
+ switch self.orientation {
+ case .landscapeRight, .landscapeLeft:
+ if !withInfoContainer {
+ self.capturedVideoWidthConstraint.constant = -UIScreen.main.bounds.width + 160
+ self.capturedVideoHeightConstraint.constant = -UIScreen.main.bounds.height + 120
+ self.viewCapturedVideo.cornerRadius = 15
+ if UIDevice.current.userInterfaceIdiom == .pad {
+ self.capturedVideoTrailingConstraint.constant = 35
+ self.capturedVideoTopConstraint.constant = -13
+ } else if UIDevice.current.hasNotch && orientation == .landscapeRight {
+ self.capturedVideoTrailingConstraint.constant = 45
+ self.capturedVideoTopConstraint.constant = -15
+ } else {
+ self.capturedVideoTrailingConstraint.constant = 15
+ self.capturedVideoTopConstraint.constant = -15
+ }
+ } else {
+ //Keep the 4:3 format of the video
+ let widthCapturedVideo = ((self.infoContainerHeightConstraint.constant - 20)/3)*4
+ self.capturedVideoHeightConstraint.constant = -UIScreen.main.bounds.height + self.infoContainerHeightConstraint.constant - 20
+ self.capturedVideoWidthConstraint.constant = -UIScreen.main.bounds.width + widthCapturedVideo
+ let leftPointInfoContainer = self.infoBlurEffect?.convert((self.infoBlurEffect?.frame.origin)!, to: nil).x ?? 0
+ self.capturedVideoTrailingConstraint.constant = leftPointInfoContainer + 10
+ self.capturedVideoTopConstraint.constant = -20
+ self.viewCapturedVideo.cornerRadius = 25
+ }
+ default:
+ if !withInfoContainer {
+ self.capturedVideoWidthConstraint.constant = -UIScreen.main.bounds.width + 120
+ self.capturedVideoHeightConstraint.constant = -UIScreen.main.bounds.height + 160
+ self.viewCapturedVideo.cornerRadius = 15
+ if UIDevice.current.userInterfaceIdiom == .pad {
+ self.capturedVideoTrailingConstraint.constant = 35
+ self.capturedVideoTopConstraint.constant = -13
+ } else if UIDevice.current.hasNotch {
+ self.capturedVideoTrailingConstraint.constant = 10
+ self.capturedVideoTopConstraint.constant = 0
+ } else {
+ self.capturedVideoTrailingConstraint.constant = 10
+ self.capturedVideoTopConstraint.constant = -5
+ }
+ } else {
+ //Keep the 4:3 format of the video
+ let widthCapturedVideo = ((self.infoContainerHeightConstraint.constant - 20)/4)*3
+ self.capturedVideoHeightConstraint.constant = -UIScreen.main.bounds.height + self.infoContainerHeightConstraint.constant - 20
+ self.capturedVideoWidthConstraint.constant = -UIScreen.main.bounds.width + widthCapturedVideo
+ let leftPointInfoContainer = self.infoBlurEffect?.convert((self.infoBlurEffect?.frame.origin)!, to: nil).x ?? 0
+ self.capturedVideoTrailingConstraint.constant = leftPointInfoContainer + 10
+ self.capturedVideoTopConstraint.constant = -20
+ self.viewCapturedVideo.cornerRadius = 25
+ }
+ }
+ }
+
func showContactInfo() {
if !self.infoContainer.isHidden {
task?.cancel()
@@ -402,29 +522,33 @@
self.infoContainer.isHidden = false
self.view.layoutIfNeeded()
- UIView.animate(withDuration: 0.4, delay: 0.0,
- options: .curveEaseOut,
- animations: { [unowned self] in
- self.infoContainer.alpha = 1
- self.buttonsContainer.alpha = 1
- self.view.layoutIfNeeded()
- }, completion: nil)
+ UIView.animate(withDuration: 0.2, animations: {
+ self.resizeCapturedVideo(withInfoContainer: true)
+ self.infoContainerTopConstraint.constant = -10
+ if UIDevice.current.hasNotch && (self.orientation == .landscapeRight || self.orientation == .landscapeLeft) {
+ self.buttonsContainerBottomConstraint.constant = 1
+ } else if UIDevice.current.userInterfaceIdiom == .pad {
+ self.buttonsContainerBottomConstraint.constant = 30
+ } else {
+ self.buttonsContainerBottomConstraint.constant = 10
+ }
+ self.view.layoutIfNeeded()
+ })
task = DispatchWorkItem { self.hideContactInfo() }
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 7, execute: task!)
}
func hideContactInfo() {
- UIView.animate(withDuration: 0.4, delay: 0.00,
- options: .curveEaseOut,
- animations: { [unowned self] in
- self.infoContainer.alpha = 0
- self.buttonsContainer.alpha = 0
- self.view.layoutIfNeeded()
- }, completion: { [weak self] _ in
- self?.infoContainer.isHidden = true
- self?.buttonsContainer.isHidden = true
- })
+ UIView.animate(withDuration: 0.2, animations: { [unowned self] in
+ self.resizeCapturedVideo(withInfoContainer: false)
+ self.infoContainerTopConstraint.constant = 150
+ self.buttonsContainerBottomConstraint.constant = -150
+ self.view.layoutIfNeeded()
+ }, completion: { [weak self] _ in
+ self?.infoContainer.isHidden = true
+ self?.buttonsContainer.isHidden = true
+ })
}
func showAllInfo() {
@@ -432,6 +556,10 @@
self.infoContainer.isHidden = false
}
+ @objc func canRotate() {
+ // empty function to support call screen rotation
+ }
+
override func viewWillDisappear(_ animated: Bool) {
UIDevice.current.setValue(Int(UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")
super.viewWillDisappear(animated)
diff --git a/Ring/Ring/Calls/CallViewModel.swift b/Ring/Ring/Calls/CallViewModel.swift
index 2cabf05..e15f7e2 100644
--- a/Ring/Ring/Calls/CallViewModel.swift
+++ b/Ring/Ring/Calls/CallViewModel.swift
@@ -310,7 +310,12 @@
let seconds = interval % 60
let minutes = (interval / 60) % 60
let hours = (interval / 3600)
- return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
+ switch hours {
+ case 0:
+ return String(format: "%02d:%02d", minutes, seconds)
+ default:
+ return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
+ }
}
func cancelCall() {
diff --git a/Ring/Ring/Extensions/Devices+Helpers.swift b/Ring/Ring/Extensions/Devices+Helpers.swift
index 3884a49..f48f85c 100644
--- a/Ring/Ring/Extensions/Devices+Helpers.swift
+++ b/Ring/Ring/Extensions/Devices+Helpers.swift
@@ -23,6 +23,15 @@
public extension UIDevice {
+ var hasNotch: Bool {
+ var bottom: CGFloat = 0
+ if #available(iOS 11.0, *) {
+ bottom = UIApplication.shared.keyWindow?.safeAreaInsets.bottom ?? 0
+ } else {
+ bottom = 0
+ }
+ return bottom > 0
+ }
static let modelName: String = {
var systemInfo = utsname()
uname(&systemInfo)
diff --git a/Ring/Ring/Extensions/UIColor+Ring.swift b/Ring/Ring/Extensions/UIColor+Ring.swift
index bc3216f..2d17df2 100644
--- a/Ring/Ring/Extensions/UIColor+Ring.swift
+++ b/Ring/Ring/Extensions/UIColor+Ring.swift
@@ -48,7 +48,6 @@
static let ringMsgTextFieldBorder = UIColor(red: 220, green: 220, blue: 220, alpha: 1.0)
static let ringUITableViewCellSelection = UIColor(red: 209, green: 210, blue: 210, alpha: 1.0)
static let ringNavigationBar = UIColor(red: 235, green: 235, blue: 235, alpha: 1.0)
- static let ringCallInfos = UIColor(hex: 0x626262, alpha: 1.0)
static let ringCallPulse = UIColor(red: 99, green: 191, blue: 208, alpha: 1.0)
static let ringSuccess = UIColor(hex: 0x00b20b, alpha: 1.0)
static let ringFailure = UIColor(hex: 0xf00000, alpha: 1.0)
diff --git a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
index ae98b04..c7fb692 100644
--- a/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
+++ b/Ring/Ring/Features/Conversations/Conversation/ConversationViewModel.swift
@@ -350,7 +350,7 @@
if self.conversation.value.messages.isEmpty {
self.sendContactRequest()
}
- self.stateSubject.onNext(ConversationState.startCall(contactRingId: self.conversation.value.recipientRingId, userName: self.userName.value))
+ self.stateSubject.onNext(ConversationState.startCall(contactRingId: self.conversation.value.recipientRingId, userName: self.displayName.value ?? self.userName.value))
}
func startAudioCall() {