diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard index cecbd930..2bdee5a2 100755 --- a/ios/Runner/Base.lproj/Main.storyboard +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -39,9 +39,15 @@ - + - + + + + + + + @@ -100,20 +106,29 @@ + + + + + - - - - - - - + @@ -128,7 +143,7 @@ - + @@ -261,7 +277,7 @@ - + @@ -275,6 +291,7 @@ + @@ -285,26 +302,33 @@ + + + + + + - + - + - + + @@ -333,7 +357,6 @@ - diff --git a/ios/Runner/Extensions.swift b/ios/Runner/Extensions.swift index c73f49e2..b79c8deb 100644 --- a/ios/Runner/Extensions.swift +++ b/ios/Runner/Extensions.swift @@ -9,12 +9,19 @@ import AADraggableView extension AADraggableView{ func enable(_ enable:Bool){ - if enable == false{ + isEnabled = enable + if enable == false{ gestureRecognizers?.forEach({ gest in removeGestureRecognizer(gest) }) - }else{ - isEnabled = true } } } + +extension UIView{ + func hidden(_ hidden:Bool, rootView:UIView){ + UIView.transition(with: rootView, duration: 0.5, options: .transitionCrossDissolve, animations: { + self.isHidden = hidden + }) + } +} diff --git a/ios/Runner/MainAppViewController.swift b/ios/Runner/MainAppViewController.swift index 87610042..c7b7a18d 100644 --- a/ios/Runner/MainAppViewController.swift +++ b/ios/Runner/MainAppViewController.swift @@ -13,9 +13,10 @@ class MainAppViewController: FlutterViewController{ var videoCallContainer:AADraggableView! var videoCallViewController:VideoCallViewController! var videoCallFlutterResult:FlutterResult? - var vdoCallViewMinConstraint:[NSLayoutConstraint]! - var vdoCallViewMaxConstraint:[NSLayoutConstraint]! - + var vdoCallViewFloatRectConstraint:[NSLayoutConstraint]! + var vdoCallViewFullConstraint:[NSLayoutConstraint]! + var vdoCallViewFloatCircleConstraint:[NSLayoutConstraint]! + override func viewDidLoad() { super.viewDidLoad() @@ -58,22 +59,20 @@ extension MainAppViewController : ICallProtocol{ view.addSubview(videoCallContainer) setVideoViewConstrints() - NSLayoutConstraint.activate(vdoCallViewMaxConstraint) - NSLayoutConstraint.deactivate(vdoCallViewMinConstraint) + NSLayoutConstraint.activate(vdoCallViewFullConstraint) + NSLayoutConstraint.deactivate(vdoCallViewFloatRectConstraint) ViewEmbedder.embed( withIdentifier: "videoCall", // Storyboard ID parent: self, container: self.videoCallContainer){ vc in self.videoCallViewController = vc as? VideoCallViewController - + } } private func showVideo(show:Bool){ - UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: { - self.videoCallContainer.isHidden = !show - }) + self.videoCallContainer.hidden(!show, rootView: view) } private func startVideoCall(result: @escaping FlutterResult, call:FlutterMethodCall) { @@ -82,14 +81,19 @@ extension MainAppViewController : ICallProtocol{ if let arguments = call.arguments as? NSDictionary{ showVideoCallView(true) - videoCallViewController.onFloat = { min in - self.floatVideoCallView(min) + videoCallViewController.onRectFloat = { isRectFloat in + self.rectFloatVideoCallView(isRectFloat) + } + + videoCallViewController.onCircleFloat = { isCircleFloat in + self.circleFloatVideoCallView(isCircleFloat) } videoCallViewController.onCallConnect = { self.videoCallChannel?.invokeMethod("onCallConnected",arguments: nil) } videoCallViewController.onCallDisconnect = { self.showVideoCallView(false) + self.videoCallViewController.minimizeVideoState(state: false) self.videoCallChannel?.invokeMethod("onCallDisconnected",arguments: nil) } videoCallViewController.callBack = self @@ -99,16 +103,18 @@ extension MainAppViewController : ICallProtocol{ } - private func floatVideoCallView(_ value:Bool){ + private func rectFloatVideoCallView(_ value:Bool){ videoCallContainer.enable(value) UIView.animate(withDuration: 0.5) { if(value){ - NSLayoutConstraint.deactivate(self.vdoCallViewMaxConstraint) - NSLayoutConstraint.activate(self.vdoCallViewMinConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint) + NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint) }else{ - NSLayoutConstraint.deactivate(self.vdoCallViewMinConstraint) - NSLayoutConstraint.activate(self.vdoCallViewMaxConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint) + NSLayoutConstraint.activate(self.vdoCallViewFullConstraint) } self.videoCallContainer.layer.cornerRadius = value ? 10 : 0 self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil @@ -117,12 +123,32 @@ extension MainAppViewController : ICallProtocol{ } } - private func showVideoCallView(_ value:Bool){ + private func circleFloatVideoCallView(_ value:Bool){ + videoCallContainer.reposition = value ? .sticky : .edgesOnly + UIView.animate(withDuration: 0.5) { - self.videoCallContainer.isHidden = !value + if(value){ + NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFloatRectConstraint) + NSLayoutConstraint.activate(self.vdoCallViewFloatCircleConstraint) + self.videoCallContainer.layer.cornerRadius = 35 + }else{ + NSLayoutConstraint.activate(self.vdoCallViewFloatRectConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFullConstraint) + NSLayoutConstraint.deactivate(self.vdoCallViewFloatCircleConstraint) + self.videoCallContainer.layer.cornerRadius = 10 + + } + self.videoCallContainer.layer.borderColor = value ? UIColor.white.cgColor : nil + self.videoCallContainer.layer.borderWidth = value ? 2 : 0 + self.view.layoutIfNeeded() } } + private func showVideoCallView(_ value:Bool){ + self.videoCallContainer.hidden(!value, rootView: view) + } + func sessionDone(res: Any) { videoCallFlutterResult?(res) } @@ -133,22 +159,32 @@ extension MainAppViewController : ICallProtocol{ func setVideoViewConstrints(){ + videoCallContainer.layer.shadowColor = UIColor.black.cgColor + videoCallContainer.layer.shadowOffset = CGSize(width: 1, height: 1) + videoCallContainer.layer.shadowRadius = 5 + let screen = UIScreen.main.bounds videoCallContainer.translatesAutoresizingMaskIntoConstraints = false - vdoCallViewMinConstraint = [ - videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 20), - videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), - videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width/3), - videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height/3.5) - ] - vdoCallViewMaxConstraint = [ + vdoCallViewFullConstraint = [ videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor), videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width), videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height) ] + vdoCallViewFloatRectConstraint = [ + videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40), + videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), + videoCallContainer.widthAnchor.constraint(equalToConstant: screen.width/3), + videoCallContainer.heightAnchor.constraint(equalToConstant: screen.height/3.5) + ] + vdoCallViewFloatCircleConstraint = [ + videoCallContainer.topAnchor.constraint(equalTo: view.topAnchor, constant: 40), + videoCallContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), + videoCallContainer.widthAnchor.constraint(equalToConstant: 70), + videoCallContainer.heightAnchor.constraint(equalToConstant: 70) + ] } } diff --git a/ios/Runner/VideoCallRequestParameters.swift b/ios/Runner/VideoCallRequestParameters.swift index 2366c562..543d7e8b 100644 --- a/ios/Runner/VideoCallRequestParameters.swift +++ b/ios/Runner/VideoCallRequestParameters.swift @@ -12,7 +12,8 @@ class VideoCallRequestParameters{ var generalId:String? var doctorId:Int? var baseUrl:String? - + var patientName:String? + init(dictionary:NSDictionary){ self.apiKey = dictionary["kApiKey"] as? String self.sessionId = dictionary["kSessionId"] as? String @@ -23,5 +24,6 @@ class VideoCallRequestParameters{ self.generalId = dictionary["generalId"] as? String self.doctorId = dictionary["DoctorId"] as? Int self.baseUrl = dictionary["baseUrl"] as? String + self.patientName = dictionary["patientName"] as? String } } diff --git a/ios/Runner/VideoCallViewController.swift b/ios/Runner/VideoCallViewController.swift index 72842057..80a6fcb8 100644 --- a/ios/Runner/VideoCallViewController.swift +++ b/ios/Runner/VideoCallViewController.swift @@ -34,8 +34,8 @@ class VideoCallViewController: UIViewController { var seconds = 55 var isUserConnect : Bool = false - var onFloat:((Bool)->Void)? = nil - var onMinimize:(()->Void)? = nil + var onRectFloat:((Bool)->Void)? = nil + var onCircleFloat:((Bool)->Void)? = nil var onCallConnect:(()->Void)? = nil var onCallDisconnect:(()->Void)? = nil @@ -50,26 +50,55 @@ class VideoCallViewController: UIViewController { @IBOutlet var minimizeConstraint: [NSLayoutConstraint]! @IBOutlet var maximisedConstraint: [NSLayoutConstraint]! + @IBOutlet weak var btnMinimize: UIButton! @IBOutlet weak var hideVideoBtn: UIButton! - @IBOutlet weak var draggableBoundryDefiner: UIView! var localVideoDraggable:AADraggableView? @IBOutlet weak var controlButtons: UIView! @IBOutlet weak var remoteVideoMutedIndicator: UIImageView! @IBOutlet weak var localVideoMutedBg: UIView! + @IBOutlet weak var btnScreenTap: UIButton! + @IBOutlet weak var localVideoContainer: UIView! + @IBOutlet weak var topBar: UIView! @IBOutlet weak var lblCallDuration: UILabel! - @IBOutlet weak var remoteVideo: UIView! - @IBOutlet weak var localVideo: UIView!{ + @IBOutlet weak var fullVideoView: UIView! + @IBOutlet weak var smallVideoView: UIView!{ didSet{ - localVideo.layer.borderColor = UIColor.white.cgColor - localVideoDraggable = localVideo?.superview as? AADraggableView + smallVideoView.layer.borderColor = UIColor.white.cgColor + localVideoDraggable = smallVideoView?.superview as? AADraggableView localVideoDraggable?.reposition = .edgesOnly } } override func viewDidLoad() { super.viewDidLoad() - localVideoDraggable?.respectedView = draggableBoundryDefiner + localVideoDraggable?.respectedView = localVideoContainer + } + + @objc func click(gesture:UIGestureRecognizer){ + gesture.view?.removeFromSuperview() + } + + @IBAction func btnOnScreenTapped(_ sender: Any) { + if(hideVideoBtn.isSelected){ + circleFloatBtnTapped(hideVideoBtn) + + }else if(btnMinimize.isSelected){ + btnMinimizeTapped(btnMinimize) + } + } + + @IBAction func btnSwipeVideoTapped(_ sender: Any) { +// let smallVdoRender = smallVideoView.subviews.first +// let fullVdoRender = fullVideoView.subviews.first +// if let vdo = smallVdoRender{ +// fullVideoView.addSubview(vdo) +// } +// if let vdo = fullVdoRender{ +// smallVideoView.addSubview(vdo) +// } +// +// layoutVideoRenderViews() } @IBAction func didClickMuteButton(_ sender: UIButton) { @@ -77,10 +106,9 @@ class VideoCallViewController: UIViewController { publisher!.publishAudio = !sender.isSelected } - @IBAction func didClickSpeakerButton(_ sender: UIButton) { + @IBAction func didClickSpeakerButton(_ sender: UIButton) { sender.isSelected = !sender.isSelected subscriber?.subscribeToAudio = !sender.isSelected - // resetHideButtonsTimer() } @IBAction func didClickVideoMuteButton(_ sender: UIButton) { @@ -90,9 +118,8 @@ class VideoCallViewController: UIViewController { } else { publisher!.publishVideo = true } - localVideo.isHidden = sender.isSelected + smallVideoView.isHidden = sender.isSelected localVideoMutedBg.isHidden = !sender.isSelected - // resetHideButtonsTimer() } @@ -104,7 +131,6 @@ class VideoCallViewController: UIViewController { } else { publisher!.cameraPosition = AVCaptureDevice.Position.back } - /// resetHideButtonsTimer() } @IBAction func hangUp(_ sender: UIButton) { @@ -112,36 +138,46 @@ class VideoCallViewController: UIViewController { sessionDisconnect() } - @IBAction func hideVideoBtnTapped(_ sender: Any) { - onMinimize?() + @IBAction func circleFloatBtnTapped(_ sender: UIButton) { + sender.isSelected = !sender.isSelected + onCircleFloat?(sender.isSelected) + topBar.isHidden = sender.isSelected + controlButtons.isHidden = sender.isSelected + smallVideoView.isHidden = sender.isSelected + self.publisher?.view?.layoutIfNeeded() } - var floated = false - @IBAction func onMinimize(_ sender: UIButton) { - floated = !floated - onFloat?(floated) - sender.isSelected = floated + @IBAction func btnMinimizeTapped(_ sender: UIButton) { + minimizeVideoState(state: !sender.isSelected) + btnScreenTap.isHidden = !sender.isSelected + } + + func minimizeVideoState(state:Bool){ + btnMinimize.isSelected = state + onRectFloat?(state) - NSLayoutConstraint.activate(floated ? minimizeConstraint : maximisedConstraint) - NSLayoutConstraint.deactivate(floated ? maximisedConstraint : minimizeConstraint) - localVideoDraggable?.enable(!floated) + NSLayoutConstraint.activate(state ? minimizeConstraint : maximisedConstraint) + NSLayoutConstraint.deactivate(state ? maximisedConstraint : minimizeConstraint) + localVideoDraggable?.enable(!state) - lblRemoteUsername.isHidden = floated - hideVideoBtn.isHidden = !floated + lblRemoteUsername.isHidden = state + hideVideoBtn.isHidden = !state lblCallDuration.superview?.isHidden = !hideVideoBtn.isHidden - let min_ = floated UIView.animate(withDuration: 0.5) { - self.videoMuteBtn.isHidden = min_ - self.micMuteBtn.isHidden = min_ - self.camSwitchBtn.isHidden = min_ - - let localVdoSize = self.localVideo.bounds.size - let remoteVdoSize = self.remoteVideo.bounds.size - self.publisher?.view?.frame = CGRect(x: 0, y: 0, width: localVdoSize.width, height: localVdoSize.height) - self.subscriber?.view?.frame = CGRect(x: 0, y: 0, width: remoteVdoSize.width, height: remoteVdoSize.height) - self.publisher?.view?.layoutIfNeeded() - self.subscriber?.view?.layoutIfNeeded() + self.videoMuteBtn.isHidden = state + self.micMuteBtn.isHidden = state + self.camSwitchBtn.isHidden = state + self.layoutVideoRenderViews() + } + } + + func layoutVideoRenderViews(){ + if let publisherVdoSize = publisher?.view?.superview?.bounds.size{ + publisher?.view?.frame = CGRect(x: 0, y: 0, width: publisherVdoSize.width, height: publisherVdoSize.height) + } + if let subscriberVdoSize = subscriber?.view?.superview?.bounds.size{ + subscriber?.view?.frame = CGRect(x: 0, y: 0, width: subscriberVdoSize.width, height: subscriberVdoSize.height) } } @@ -161,6 +197,9 @@ class VideoCallViewController: UIViewController { } func start(params:VideoCallRequestParameters){ + lblRemoteUsername.text = params.patientName ?? "- - -" + btnScreenTap.isHidden = true + hideVideoBtn.isHidden = true self.kApiKey = params.apiKey ?? "" self.kSessionId = params.sessionId ?? "" @@ -171,11 +210,11 @@ class VideoCallViewController: UIViewController { self.DoctorId = params.doctorId ?? 0 self.baseUrl = params.baseUrl ?? "" - setupButtons() askForMicrophonePermission() requestCameraPermissionsIfNeeded() hideVideoMuted() setupSession() + } private func changeCallStatus(callStatus:Int){ @@ -238,13 +277,6 @@ class VideoCallViewController: UIViewController { } } - - func setupButtons() { - perform(#selector(hideControlButtons), with: nil, afterDelay: 3) - let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(remoteVideoTapped(_:))) - view.addGestureRecognizer(tapGestureRecognizer) - view.isUserInteractionEnabled = true - } // MARK: -Microphone Camera and Permission Request func askForMicrophonePermission() { @@ -387,10 +419,11 @@ extension VideoCallViewController: OTSessionDelegate { showAlert(error?.localizedDescription) } - publisher?.view!.frame = CGRect(x: 0, y: 0, width: localVideo.bounds.size.width, height: localVideo.bounds.size.height) + publisher?.view?.tag = 11 publisher?.view?.layer.cornerRadius = 5 publisher?.view?.clipsToBounds = true - localVideo.addSubview((publisher?.view)!) + smallVideoView.addSubview((publisher?.view)!) + layoutVideoRenderViews() } func sessionDidDisconnect(_ session: OTSession) { @@ -430,9 +463,9 @@ extension VideoCallViewController: OTSessionDelegate { guard let subscriberView = subscriber.view else { return } - - subscriberView.frame = CGRect(x: 0, y: 0, width: remoteVideo.bounds.width, height: remoteVideo.bounds.height) - remoteVideo.addSubview(subscriberView) + subscriberView.tag = 22 + fullVideoView.addSubview(subscriberView) + layoutVideoRenderViews() startUpdateCallDuration() onCallConnect?() @@ -481,12 +514,6 @@ extension VideoCallViewController: OTPublisherDelegate { func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) { print("The publisher failed: \(error)") } - @objc func remoteVideoTapped(_ recognizer: UITapGestureRecognizer?) { - if controlButtons.isHidden { - controlButtons.isHidden = false - perform(#selector(hideControlButtons), with: nil, afterDelay: 3) - } - } } extension VideoCallViewController: OTSubscriberDelegate { @@ -497,8 +524,5 @@ extension VideoCallViewController: OTSubscriberDelegate { public func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) { print("The subscriber failed to connect to the stream.") } - @objc func hideControlButtons() { -// controlButtons.isHidden = true - } }