Commit b32227fb authored by Quentin Muret's avatar Quentin Muret Committed by Quentin Muret

call view: hide preview on tap or swipe

Add the possibility to hide the video thumbnail by swiped or tapped
on it.

Change-Id: I2f73511fd20935132c280be6565fcf4ef17f45e6
Reviewed-by: Kateryna Kostiuk<kateryna.kostiuk@savoirfairelinux.com>
parent 5006b726
......@@ -140,13 +140,23 @@
<color key="backgroundColor" red="0.99999600649999998" green="1" blue="1" alpha="0.17999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
<blurEffect style="light"/>
</visualEffectView>
<imageView userInteractionEnabled="NO" alpha="0.0" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" image="left_arrow" translatesAutoresizingMaskIntoConstraints="NO" id="gWE-IS-b5p">
<rect key="frame" x="67" y="364" width="240" height="128"/>
<color key="tintColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="60" id="ATJ-SU-7iG"/>
<constraint firstAttribute="height" constant="70" id="iha-aS-TZH"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint firstItem="gWE-IS-b5p" firstAttribute="centerY" secondItem="rt7-JS-vjg" secondAttribute="centerY" id="1Jq-i7-iGP"/>
<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="gWE-IS-b5p" firstAttribute="leading" secondItem="rt7-JS-vjg" secondAttribute="leading" constant="-17" id="kOS-1k-vY1"/>
<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"/>
......@@ -255,6 +265,7 @@
<constraints>
<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="ZK1-Be-lcD" firstAttribute="leading" relation="lessThanOrEqual" secondItem="lZI-X0-bkP" secondAttribute="trailing" constant="-25" id="5UD-4Q-iDL"/>
<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"/>
......@@ -276,7 +287,6 @@
</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="avatarViewBlurEffect" destination="uC8-vY-dHO" id="lJD-lK-7CI"/>
<outlet property="avatarViewImageTopConstraint" destination="82d-fj-m0F" id="z3A-J5-tFD"/>
......@@ -302,6 +312,7 @@
<outlet property="infoContainer" destination="3RN-4M-qR4" id="CUO-h6-mFf"/>
<outlet property="infoContainerHeightConstraint" destination="b8L-UJ-IKC" id="U6k-oI-MPH"/>
<outlet property="infoContainerTopConstraint" destination="G1C-hv-89U" id="MFr-jm-kBk"/>
<outlet property="leftArrow" destination="gWE-IS-b5p" id="Kxj-Fb-zuK"/>
<outlet property="mainView" destination="QpJ-Sx-9dG" id="0y9-R4-q5W"/>
<outlet property="nameLabel" destination="73Y-N1-Yga" id="XcQ-V6-ZrF"/>
<outlet property="profileImageView" destination="fnt-PQ-Q6P" id="MgB-Ev-bTc"/>
......@@ -318,5 +329,6 @@
</scenes>
<resources>
<image name="ic_contact_picture" width="256" height="256"/>
<image name="left_arrow" width="138.24000549316406" height="138.24000549316406"/>
</resources>
</document>
......@@ -25,6 +25,7 @@ import RxSwift
import Reusable
import SwiftyBeaver
// swiftlint:disable type_body_length
class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
//preview screen
......@@ -52,6 +53,7 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
@IBOutlet private weak var callInfoTimerLabel: UILabel!
@IBOutlet private weak var buttonsContainer: ButtonsContainerView!
@IBOutlet weak var infoBlurEffect: UIVisualEffectView!
@IBOutlet weak var leftArrow: UIImageView!
//Constraints
@IBOutlet weak var capturedVideoWidthConstraint: NSLayoutConstraint!
......@@ -69,6 +71,8 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
var viewModel: CallViewModel!
var isCallStarted: Bool = false
var isMenuShowed = false
var isVideoHidden = false
var orientation = UIDevice.current.orientation
fileprivate let disposeBag = DisposeBag()
......@@ -83,6 +87,14 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
super.viewDidLoad()
self.setAvatarView(true)
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(screenTapped))
let tapCapturedVideo = UITapGestureRecognizer(target: self, action: #selector(hideCapturedVideo))
let swipeLeftCapturedVideo = UISwipeGestureRecognizer(target: self, action: #selector(capturedVideoSwipped(gesture:)))
swipeLeftCapturedVideo.direction = .left
let swipeRightCapturedVideo = UISwipeGestureRecognizer(target: self, action: #selector(capturedVideoSwipped(gesture:)))
swipeRightCapturedVideo.direction = .right
self.viewCapturedVideo.addGestureRecognizer(tapCapturedVideo)
self.viewCapturedVideo.addGestureRecognizer(swipeLeftCapturedVideo)
self.viewCapturedVideo.addGestureRecognizer(swipeRightCapturedVideo)
self.mainView.addGestureRecognizer(tapGestureRecognizer)
self.setUpCallButtons()
self.setupBindings()
......@@ -112,14 +124,32 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
initCallAnimation()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
@objc func capturedVideoSwipped(gesture: UISwipeGestureRecognizer) {
if self.avatarView.isHidden == false { return }
if gesture.direction == UISwipeGestureRecognizerDirection.left && (self.isVideoHidden == false) { return }
if gesture.direction == UISwipeGestureRecognizerDirection.right && (self.isVideoHidden == true) { return }
self.hideCapturedVideo()
}
@objc func hideCapturedVideo() {
if self.isMenuShowed { return }
UIView.animate(withDuration: 0.3, animations: {
if self.capturedVideoBlurEffect.alpha == 0 {
self.isVideoHidden = true
self.capturedVideoBlurEffect.alpha = 1
} else {
self.isVideoHidden = false
self.capturedVideoBlurEffect.alpha = 0
}
self.resizeCapturedVideo(withInfoContainer: !self.infoContainer.isHidden)
self.view.layoutIfNeeded()
})
}
func setWhiteAvatarView() {
UIApplication.shared.statusBarStyle = .default
self.callPulse.backgroundColor = UIColor.ringCallPulse
self.avatarView.backgroundColor = UIColor.white
UIApplication.shared.statusBarStyle = .default
self.callPulse.backgroundColor = UIColor.ringCallPulse
self.avatarView.backgroundColor = UIColor.white
}
func initCallAnimation() {
......@@ -317,6 +347,16 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
.bind(to: self.capturedVideo.rx.isHidden)
.disposed(by: self.disposeBag)
self.viewModel.videoMuted
.observeOn(MainScheduler.instance)
.bind(to: self.capturedVideoBlurEffect.rx.isHidden)
.disposed(by: self.disposeBag)
self.viewModel.videoMuted
.observeOn(MainScheduler.instance)
.bind(to: self.leftArrow.rx.isHidden)
.disposed(by: self.disposeBag)
if !self.viewModel.isAudioOnly {
self.viewModel.callPaused
.observeOn(MainScheduler.instance)
......@@ -387,26 +427,26 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
func resizeCapturedFrame() {
self.viewModel.showCapturedFrame
.observeOn(MainScheduler.instance)
.subscribe(onNext: { dontShow in
if dontShow && !self.isCallStarted {
self.isCallStarted = true
self.hideCancelButton()
.subscribe(onNext: { [weak self] dontShow in
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
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
self.resizeCapturedVideo(withInfoContainer: false)
self.capturedVideoBlurEffect.alpha = 0
self.view.layoutIfNeeded()
}, completion: nil)
self.avatarViewBlurEffect.alpha = CGFloat(1)
UIView.animate(withDuration: 0.4, animations: {
self?.resizeCapturedVideo(withInfoContainer: false)
self?.capturedVideoBlurEffect.alpha = 0
self?.view.layoutIfNeeded()
}, completion: nil)
self?.avatarViewBlurEffect.alpha = CGFloat(1)
}
}).disposed(by: self.disposeBag)
}
......@@ -455,6 +495,7 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
}
func resizeCapturedVideo(withInfoContainer: Bool) {
self.leftArrow.alpha = 0
//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
......@@ -511,6 +552,11 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
self.viewCapturedVideo.cornerRadius = 25
}
}
if self.capturedVideoBlurEffect.alpha == 1 && self.isMenuShowed == false
&& self.avatarView.isHidden == true {
self.leftArrow.alpha = 1
self.capturedVideoTrailingConstraint.constant = -200
}
}
func showContactInfo() {
......@@ -519,11 +565,13 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
self.hideContactInfo()
return
}
self.isMenuShowed = true
self.buttonsContainer.isHidden = false
self.infoContainer.isHidden = false
self.view.layoutIfNeeded()
UIView.animate(withDuration: 0.2, animations: {
self.capturedVideoBlurEffect.alpha = 0
self.resizeCapturedVideo(withInfoContainer: true)
self.infoContainerTopConstraint.constant = -10
if UIDevice.current.hasNotch && (self.orientation == .landscapeRight || self.orientation == .landscapeLeft) {
......@@ -541,7 +589,9 @@ class CallViewController: UIViewController, StoryboardBased, ViewModelBased {
}
func hideContactInfo() {
self.isMenuShowed = false
UIView.animate(withDuration: 0.2, animations: { [unowned self] in
if self.isVideoHidden { self.capturedVideoBlurEffect.alpha = 1 }
self.resizeCapturedVideo(withInfoContainer: false)
self.infoContainerTopConstraint.constant = 150
self.buttonsContainerBottomConstraint.constant = -150
......
......@@ -40,6 +40,7 @@ internal enum Asset {
internal static let enableSpeakerphone = ImageAsset(name: "enable_speakerphone")
internal static let fallbackAvatar = ImageAsset(name: "fallback_avatar")
internal static let icContactPicture = ImageAsset(name: "ic_contact_picture")
internal static let leftArrow = ImageAsset(name: "left_arrow")
internal static let moreSettings = ImageAsset(name: "more_settings")
internal static let pauseCall = ImageAsset(name: "pause_call")
internal static let qrCode = ImageAsset(name: "qr_code")
......
{
"images" : [
{
"idiom" : "universal",
"filename" : "Icon-60.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "Icon-128.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "Icon-144.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "template"
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment