| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -1,12 +1,23 @@
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import UIKit
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				import WebRTC
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				final class MiniCallView: UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				final class MiniCallView: UIView, RTCVideoViewDelegate {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    var callVC: CallVC
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private lazy var remoteVideoView: RemoteVideoView = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let result = RemoteVideoView()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.alpha = 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // MARK: UI
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private static let defaultSize: CGFloat = 100
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var width: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var height: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var left: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var right: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var top: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private var bottom: NSLayoutConstraint?
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private lazy var remoteVideoView: RTCMTLVideoView = {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let result = RTCMTLVideoView()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.delegate = self
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.alpha = self.callVC.call.isRemoteVideoEnabled ? 1 : 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.videoContentMode = .scaleAspectFit
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        result.backgroundColor = .black
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        return result
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -22,6 +33,17 @@ final class MiniCallView: UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setUpViewHierarchy()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        setUpGestureRecognizers()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        MiniCallView.current = self
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.callVC.call.remoteVideoStateDidChange = { isEnabled in
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            DispatchQueue.main.async {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                UIView.animate(withDuration: 0.25) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    self.remoteVideoView.alpha = isEnabled ? 1 : 0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    if !isEnabled {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.width?.constant = MiniCallView.defaultSize
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                        self.height?.constant = MiniCallView.defaultSize
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				                }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    override init(frame: CGRect) {
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -33,8 +55,8 @@ final class MiniCallView: UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    private func setUpViewHierarchy() {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.set(.width, to: 100)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.set(.height, to: 100)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.width = self.set(.width, to: MiniCallView.defaultSize)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.height = self.set(.height, to: MiniCallView.defaultSize)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.layer.cornerRadius = 10
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.layer.masksToBounds = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        // Background
 | 
			
		
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
			
			 | 
			 | 
			
				@ -80,9 +102,13 @@ final class MiniCallView: UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.alpha = 0.0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let window = CurrentAppContext().mainWindow!
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        window.addSubview(self)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.autoPinEdge(toSuperviewEdge: .right)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        left = self.autoPinEdge(toSuperviewEdge: .left)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        left?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        right = self.autoPinEdge(toSuperviewEdge: .right)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let topMargin = UIApplication.shared.keyWindow!.safeAreaInsets.top + Values.veryLargeSpacing
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        top = self.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        bottom = self.autoPinEdge(toSuperviewEdge: .bottom)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        bottom?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        UIView.animate(withDuration: 0.5, delay: 0, options: [], animations: {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.alpha = 1.0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }, completion: nil)
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
			
			 | 
			 | 
			
				@ -93,9 +119,42 @@ final class MiniCallView: UIView {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.alpha = 0.0
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }, completion: { _ in
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.callVC.call.removeRemoteVideoRenderer(self.remoteVideoView)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.callVC.setupStateChangeCallbacks()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            MiniCallView.current = nil
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            self.removeFromSuperview()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        })
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    // MARK: RTCVideoViewDelegate
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    func videoView(_ videoView: RTCVideoRenderer, didChangeVideoSize size: CGSize) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let newSize = CGSize(width: min(160.0, 160.0 * size.width / size.height), height: min(160.0, 160.0 * size.height / size.width))
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        persistCurrentPosition(newSize: newSize)
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.width?.constant = newSize.width
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        self.height?.constant = newSize.height
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    func persistCurrentPosition(newSize: CGSize) {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let currentCenter = self.center
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if currentCenter.x < self.superview!.width() / 2 {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            left?.isActive = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            right?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            left?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            right?.isActive = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let willTouchTop = currentCenter.y < newSize.height / 2
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        let willTouchBottom = currentCenter.y + newSize.height / 2 >= self.superview!.height()
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        if willTouchBottom {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            top?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            bottom?.isActive = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        } else {
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            let constant = willTouchTop ? 0 : currentCenter.y - newSize.height / 2
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            top?.constant = constant
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            top?.isActive = true
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				            bottom?.isActive = false
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				        }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				    }
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				
 | 
			
		
		
	
		
			
				 | 
				 | 
			
			 | 
			 | 
			
				}
 | 
			
		
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
			
			 | 
			 | 
			
				
 
 |