diff --git a/Nynja.xcodeproj/project.pbxproj b/Nynja.xcodeproj/project.pbxproj index fdc47ca429ae8db7dedf53248e3cc15cacbdc91d..3d70f4949a73bd52a4b839ca9c474acbb0242a90 100644 --- a/Nynja.xcodeproj/project.pbxproj +++ b/Nynja.xcodeproj/project.pbxproj @@ -1066,6 +1066,8 @@ 986BE2204D6D0813B13618B1 /* AddContactViaPhonePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929DD72B2F10916CF6C383F6 /* AddContactViaPhonePresenter.swift */; }; 990A25B2C84CE09B4CE64533 /* MyGroupAliasPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC9D0CBC2BAD6DC6C7047A26 /* MyGroupAliasPresenter.swift */; }; 99B9D27D2F0EFE051E6581ED /* CreateGroupProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE9DC6ADA0E71241C49A328 /* CreateGroupProtocols.swift */; }; + 9BB33F3E2146A14B009FB252 /* TapToSpeakView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BB33F3D2146A14B009FB252 /* TapToSpeakView.swift */; }; + 9BB33F412146CC7C009FB252 /* CallInProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BB33F402146CC7C009FB252 /* CallInProgressView.swift */; }; 9BC9657620FF042E00052AE1 /* CallInProgressProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC9657520FF042D00052AE1 /* CallInProgressProtocols.swift */; }; 9BD8E3F120EF7898001384EC /* CallInProgressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD8E3EF20EF7898001384EC /* CallInProgressViewController.swift */; }; 9BD8E40720F3576F001384EC /* CallInProgressWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BD8E40620F3576F001384EC /* CallInProgressWireframe.swift */; }; @@ -3130,6 +3132,8 @@ 92F29C1A91BF5FD3A0AEEA0D /* AddContactInteractor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = AddContactInteractor.swift; sourceTree = ""; }; 997E1A59FCAB5602A049C6E7 /* EditUsernamePresenter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = EditUsernamePresenter.swift; sourceTree = ""; }; 9B810991D7143259040DCA31 /* LanguageSettingsViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LanguageSettingsViewController.swift; sourceTree = ""; }; + 9BB33F3D2146A14B009FB252 /* TapToSpeakView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TapToSpeakView.swift; sourceTree = ""; }; + 9BB33F402146CC7C009FB252 /* CallInProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInProgressView.swift; sourceTree = ""; }; 9BC9657520FF042D00052AE1 /* CallInProgressProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallInProgressProtocols.swift; sourceTree = ""; }; 9BD8E3EF20EF7898001384EC /* CallInProgressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInProgressViewController.swift; sourceTree = ""; }; 9BD8E40620F3576F001384EC /* CallInProgressWireframe.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallInProgressWireframe.swift; sourceTree = ""; }; @@ -10198,6 +10202,8 @@ A895793051E246613AC4F30F /* View */ = { isa = PBXGroup; children = ( + 9BB33F3D2146A14B009FB252 /* TapToSpeakView.swift */, + 9BB33F402146CC7C009FB252 /* CallInProgressView.swift */, 6D67310F1F29E1F4003E8F8F /* BottomCallView.swift */, 6D5168A11F30430900DA3728 /* SpeakerView.swift */, 6D5157CF1F30B36A002A27DB /* ChatView.swift */, @@ -13807,6 +13813,7 @@ 8509452B206E684300B43C1C /* AddParticipantsContactCell.swift in Sources */, 3ABCE8F11EC9330D00A80B15 /* AppDelegate.swift in Sources */, 4B1D7E052029CF2900703228 /* ShareContactsItemsFactory.swift in Sources */, + 9BB33F412146CC7C009FB252 /* CallInProgressView.swift in Sources */, 853801262052C853002C6960 /* TextCheckmarkCellModel.swift in Sources */, F105C6AC20A0DCC70091786A /* UIImagePickerControllerCameraCaptureModeExtensions.swift in Sources */, A42D51A6206A361400EEB952 /* process.swift in Sources */, @@ -15002,6 +15009,7 @@ A45F112020B4218D00F45004 /* InfoInjectible.swift in Sources */, A42D52B3206A53AA00EEB952 /* Search_Spec.swift in Sources */, 850571212050B0AD00EDF794 /* NotificationAlertSoundsPresenter.swift in Sources */, + 9BB33F3E2146A14B009FB252 /* TapToSpeakView.swift in Sources */, 850C0B5420E0369E003341D0 /* ChatListMessageCellModelDelegate.swift in Sources */, A432CF1220B4347D00993AFB /* InputInfoProvider.swift in Sources */, A43B25A320AB1DFA00FF8107 /* CountryModel.swift in Sources */, diff --git a/Nynja/Modules/Call/CallScreens/CallInProgress/View/CallInProgressViewController.swift b/Nynja/Modules/Call/CallScreens/CallInProgress/View/CallInProgressViewController.swift index 723465cda686ed80125bafeb745ff55286dbebf2..931b24346a4ed4453dc8ee1512640e1f04bc233b 100644 --- a/Nynja/Modules/Call/CallScreens/CallInProgress/View/CallInProgressViewController.swift +++ b/Nynja/Modules/Call/CallScreens/CallInProgress/View/CallInProgressViewController.swift @@ -36,7 +36,7 @@ enum CallInProgressMode { import UIKit -class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCallViewProtocol, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, GroupCollectionViewCellDelegate, GroupAddParticipantsCollectionViewCellDelegate, SpeakerDelegate { +class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, GroupCollectionViewCellDelegate, GroupAddParticipantsCollectionViewCellDelegate, SpeakerDelegate, TapToSpeakViewDelegate, CallInProgressViewDelegate, UIScrollViewDelegate { var presenter: CallInProgressPresenterProtocol! var contact: Contact? @@ -47,14 +47,11 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa var roomId: String = "" let bottomViewHeight: Float = 188.0 - let labelNameHeight: Float = 40.0 - let labelStatusHeight: Float = 30.0 let offset: Float = 10.0 - let middleGVHeight: Float = 100.0 let statusBarHeight: Float = Float(UIApplication.shared.statusBarFrame.size.height) + var lastPageSelected = -1 var isIncomingCallRinging = false - var collapsed: Bool = false var initialized: Bool = false var needLocalRenderer: Bool = false var needRemoteRenderer: Bool = false @@ -112,599 +109,111 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa return sections }() - lazy var backgroundGradientView: UIView = { + lazy var callInProgressView: CallInProgressView = { - let view = GradientView(colors: [Constants.colors.callGradientStart.getColor(), - Constants.colors.callGradientEnd.getColor()]) - self.view.addSubview(view) + let view = CallInProgressView() + view.backgroundColor = Constants.colors.callBackground.getColor() + view.delegate = self + + view.collectionView.delegate = self + view.collectionView.dataSource = self + + AudioManager.sharedInstance.speakerDelegate = self + + view.isMuted = isMuted() + view.isCameraRunning = isCameraRunning() + + self.scrollView.addSubview(view) view.snp.makeConstraints({ (make) in - make.top.left.right.equalTo(self.view) - make.height.equalTo(ConstraintConstants.gradientHeight.adjustedByWidth) - }) - - return view - }() - - lazy var backgroundImage: UIImageView = { + make.top.equalToSuperview() + make.left.equalTo(self.tapToSpeakView.snp.right) + make.width.equalToSuperview() + make.height.equalToSuperview() - let img = UIImageView() - img.isUserInteractionEnabled = true - img.contentMode = .scaleAspectFill - img.backgroundColor = .clear - self.view.addSubview(img) - - img.snp.makeConstraints({ (make) in - make.top.left.right.equalTo(self.view) - make.bottom.equalTo(self.bottomView.snp.top).offset(-offset/2) - }) - return img - }() - - lazy var otherVideoView: UIView = { - - let view = UIView() - view.isUserInteractionEnabled = true - view.backgroundColor = self.view.backgroundColor - self.view.addSubview(view) - - view.snp.makeConstraints({ (make) in - make.top.left.right.equalTo(self.view) - make.bottom.equalTo(self.bottomView.snp.top).offset(-offset/2) }) + return view }() - - lazy var myVideoView: UIView = { - - let view = UIView() - view.isUserInteractionEnabled = true - view.backgroundColor = .clear - self.view.addSubview(view) - + + lazy var tapToSpeakView: TapToSpeakView = { + + let view = TapToSpeakView() + view.delegate = self + view.backgroundColor = Constants.colors.callBackground.getColor() + self.scrollView.addSubview(view) + view.snp.makeConstraints({ (make) in - make.left.equalTo(self.view).offset(ConstraintConstants.myVideoViewLeftInset.adjustedByWidth) - make.bottom.equalTo(self.otherVideoView.snp.bottom).offset(-ConstraintConstants.myVideoViewBottomInset.adjustedByWidth) - make.width.equalTo(ConstraintConstants.myVideoViewWidth.adjustedByWidth) - make.height.equalTo(ConstraintConstants.myVideoViewHeight.adjustedByWidth) - }) - return view - }() - - lazy var switchCameraButton: UIButton = { - - let btn = UIButton() - let img = #imageLiteral(resourceName: "switch_camera") - btn.backgroundColor = .clear - btn.setImage(img, for: .normal) - self.view.addSubview(btn) - - btn.addTarget(self, action: #selector(switchCameraButtonPressed), for: .touchUpInside) - - btn.snp.makeConstraints({ (make) in - make.right.equalTo(self.view).offset(-offset) - make.bottom.equalTo(self.otherVideoView.snp.bottom).offset(-offset) - make.width.height.equalTo(44) - }) - return btn - }() - - lazy var collectionView: UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .vertical - layout.minimumLineSpacing = 0 - layout.minimumInteritemSpacing = 0 - let cv = GroupCollectionView(frame: .zero, collectionViewLayout: layout) - cv.isUserInteractionEnabled = true - self.view.addSubview(cv) - cv.delegate = self - cv.dataSource = self - cv.backgroundColor = Constants.colors.callBackground.getColor() - - cv.register(GroupCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: GroupCollectionViewCell.self)) - cv.register(GroupAddParticipantsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: GroupAddParticipantsCollectionViewCell.self)) - - cv.snp.makeConstraints({ (make) in - make.top.equalTo(self.statusLabel.snp.bottom).offset(offset) - make.left.right.equalTo(self.view) - make.bottom.equalTo(self.openCloseCallsButton.snp.top).offset(-offset/2) - - }) - return cv - }() - - private lazy var nameLabel: UILabel = { - let scwidth = UIScreen.main.bounds.width - let lbl = UILabel() - lbl.textAlignment = .center - lbl.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelNameFontSize) - lbl.textColor = Constants.colors.white.getColor() - lbl.numberOfLines = 1 - lbl.baselineAdjustment = .alignCenters - lbl.lineBreakMode = .byTruncatingTail - self.view.addSubview(lbl) - - lbl.snp.makeConstraints({ (make) in - make.top.equalTo(self.view).offset(6*offset) - make.left.right.equalTo(self.view).offset(offset) - make.height.equalTo(lbl.font.lineHeight) - }) - - return lbl - }() - - private lazy var statusLabel: UILabel = { - let scwidth = UIScreen.main.bounds.width - let lbl = UILabel() - lbl.textAlignment = .center - lbl.font = UIFont(name: Constants.fonts.regular, size: ConstraintConstants.labelStatusFontSize) - lbl.textColor = Constants.colors.white.getColor() - lbl.backgroundColor = .clear - lbl.numberOfLines = 1 - lbl.adjustsFontSizeToFitWidth = true - lbl.baselineAdjustment = .alignCenters - lbl.lineBreakMode = .byClipping - self.view.addSubview(lbl) - - lbl.snp.makeConstraints({ (make) in - make.top.equalTo(self.nameLabel.snp.bottom).offset(offset) - make.left.right.equalTo(self.view).offset(offset) - make.height.equalTo(lbl.font.lineHeight) - }) - - return lbl - }() - - lazy var bottomView : UIView = { - - let view = UIView() - view.isUserInteractionEnabled = true - view.backgroundColor = .clear - self.view.addSubview(view) + + make.top.left.equalToSuperview() + make.width.equalToSuperview() + make.height.equalToSuperview() - view.snp.makeConstraints({ (make) in - make.bottom.left.right.equalTo(self.view) - make.height.equalTo(self.bottomViewHeight) }) - + return view }() - lazy var bottomViewAcceptReject : UIView = { + lazy var scrollView: UIScrollView = { - let view = UIView() - view.isUserInteractionEnabled = true - view.backgroundColor = .clear - self.view.addSubview(view) + let scroll = UIScrollView() + scroll.delegate = self + scroll.contentSize = CGSize(width: UIScreen.main.bounds.size.width*2, height: UIScreen.main.bounds.size.height) + scroll.isPagingEnabled = true + scroll.showsVerticalScrollIndicator = false - view.snp.makeConstraints({ (make) in - make.bottom.left.right.equalTo(self.view) - make.height.equalTo(self.bottomViewHeight) + self.view.addSubview(scroll) + + scroll.snp.makeConstraints({ (make) in + make.top.bottom.left.right.equalTo(self.view) }) - return view + return scroll }() - lazy var rejectButton : UIButton = { - let btn = UIButton() - let img = UIImage.init(named:"ic_decline_call") - btn.backgroundColor = .clear - btn.setImage(img, for: .normal) - self.bottomViewAcceptReject.addSubview(btn) - btn.addTarget(self, action: #selector(rejectButtonPressed), for: .touchUpInside) - let center = UIScreen.main.bounds.width / 3.0 + lazy var pageControl: UIPageControl = { + let page = UIPageControl() + page.numberOfPages = 2; + page.addTarget(self, action: #selector(changePage), for: .valueChanged) + page.backgroundColor = .clear + page.pageIndicatorTintColor = Constants.colors.darkRed.getColor() + page.currentPageIndicatorTintColor = Constants.colors.red.getColor() - btn.snp.makeConstraints({ (make) in - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.centerY.equalTo(self.bottomViewAcceptReject.snp.centerY) - make.centerX.equalTo(self.view).offset(-center + ConstraintConstants.declineButtonSize/2) - }) - return btn - }() + self.view.addSubview(page) - lazy var acceptButton : UIButton = { - let btn = UIButton() - let img = UIImage.init(named:"ic_accept_call_big") - btn.backgroundColor = .clear - btn.setImage(img, for: .normal) - self.bottomViewAcceptReject.addSubview(btn) - btn.addTarget(self, action: #selector(acceptButtonPressed), for: .touchUpInside) - let center = UIScreen.main.bounds.width / 3.0 - - btn.snp.makeConstraints({ (make) in - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.centerY.equalTo(self.bottomViewAcceptReject.snp.centerY) - make.centerX.equalTo(self.view).offset(center - ConstraintConstants.declineButtonSize/2) - }) - return btn - }() - - lazy var declineButton : UIButton = { - let btn = UIButton() - let img = UIImage.init(named:"ic_decline_call") - btn.backgroundColor = .clear - btn.setImage(img, for: .normal) - self.bottomView.addSubview(btn) - btn.addTarget(self, action: #selector(declineButtonPressed), for: .touchUpInside) - - btn.snp.makeConstraints({ (make) in - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.width.height.equalTo(ConstraintConstants.declineButtonSize) - make.bottom.equalTo(self.view).offset(-ConstraintConstants.bottomOffset) + page.snp.makeConstraints({ (make) in make.centerX.equalTo(self.view) + make.bottom.equalTo(self.view).offset(-3*offset) + make.width.equalTo(90.adjustedByHeight) + make.height.equalTo(30.adjustedByHeight) }) - return btn - }() - - lazy var speakerButton : UIButton = { - - let btn = UIButton() - - AudioManager.sharedInstance.speaker = .soft - - btn.setImage(#imageLiteral(resourceName: "ic_speaker_off"), for: .normal) - btn.setImage(#imageLiteral(resourceName: "ic_speaker_on"), for: .selected) - btn.isSelected = (AudioManager.sharedInstance.speaker == .loud) - AudioManager.sharedInstance.speakerDelegate = self - - btn.layer.masksToBounds = true - btn.isEnabled = false - self.bottomView.addSubview(btn) - let offsetX = UIScreen.main.bounds.width / 3.0 - btn.addTarget(self, action: #selector(speakerButtonPressed), for: .touchUpInside) - - btn.snp.makeConstraints({ (make) in - make.width.equalTo(ConstraintConstants.buttonSize) - make.height.equalTo(ConstraintConstants.buttonSize) - make.centerX.equalTo(self.bottomView).offset(-offsetX) - make.centerY.equalTo(self.declineButton.snp.centerY) - }) - return btn - }() - - lazy var speakerLabel: UILabel = { - let label = UILabel() - label.text = "speakerphone".localized - label.textColor = .white - label.textAlignment = .center - label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) - self.bottomView.addSubview(label) - - label.snp.makeConstraints({ (make) in - make.top.equalTo(self.speakerButton.snp.bottom).offset(0) - make.centerX.equalTo(self.speakerButton) - }) - - return label - }() - - lazy var cameraLabel: UILabel = { - let label = UILabel() - label.text = "turn_on_video".localized - label.textColor = .white - label.textAlignment = .center - label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) - self.bottomView.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.centerX.equalTo(self.view).offset(-offsetX) - make.bottom.equalTo(self.declineButton.snp.top).offset(-2*offset) - }) - - return label - }() - - lazy var cameraButton: UIButton = { - let button = UIButton() - let image = self.isCameraRunning() ? #imageLiteral(resourceName: "ic_video_on_voice_call") : #imageLiteral(resourceName: "ic_video_off_voice_call") - button.setImage(image, for: .normal) - button.addTarget(self, action: #selector(onCameraButtonPressed), for: .touchUpInside) - button.isEnabled = false - self.bottomView.addSubview(button) - let offsetX = UIScreen.main.bounds.width / 3.0 - - button.snp.makeConstraints({ (make) in - make.height.equalTo(ConstraintConstants.buttonSize) - make.width.equalTo(ConstraintConstants.buttonSize) - make.centerX.equalTo(self.bottomView).offset(-offsetX) - make.bottom.equalTo(self.cameraLabel.snp.top).offset(0) - }) - - return button - }() - - lazy var microphoneButton : UIButton = { - let btn = UIButton() - let muteImage = (self.isMuted()) ? #imageLiteral(resourceName: "ic_mute_voice_call"): #imageLiteral(resourceName: "ic_unmute_voice_call") - btn.setImage(muteImage, for: .normal) - btn.isEnabled = false - btn.layer.masksToBounds = true - self.bottomView.addSubview(btn) - btn.addTarget(self, action: #selector(microphoneButtonPressed), for: .touchUpInside) - - btn.snp.makeConstraints({ (make) in - make.width.equalTo(ConstraintConstants.buttonSize) - make.height.equalTo(ConstraintConstants.buttonSize) - make.centerY.equalTo(self.cameraButton.snp.centerY).offset(0) - make.centerX.equalTo(self.bottomView) - }) - return btn - }() - - lazy var muteLabel: UILabel = { - let label = UILabel() - label.text = "mute_call".localized - label.textColor = .white - label.textAlignment = .center - label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) - self.bottomView.addSubview(label) - - label.snp.makeConstraints({ (make) in - make.centerY.equalTo(self.cameraLabel.snp.centerY).offset(0) - make.centerX.equalTo(self.microphoneButton) - }) - - return label - }() - - lazy var messageButton : UIButton = { - let btn = UIButton() - let img = #imageLiteral(resourceName: "ic_go_to_chat") - btn.setImage(img, for: .normal) - self.bottomView.addSubview(btn) - let offsetX = UIScreen.main.bounds.width / 3.0 - btn.addTarget(self, action: #selector(messageButtonPressed), for: .touchUpInside) - btn.isEnabled = false - btn.snp.makeConstraints({ (make) in - make.width.equalTo(ConstraintConstants.buttonSize) - make.height.equalTo(ConstraintConstants.buttonSize) - make.centerX.equalTo(self.bottomView).offset(offsetX) - make.centerY.equalTo(self.declineButton.snp.centerY) - }) - return btn - }() - - lazy var chatLabel: UILabel = { - let label = UILabel() - label.text = "return_to_chat_from_call".localized - label.textColor = .white - label.textAlignment = .center - label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) - self.bottomView.addSubview(label) - - label.snp.makeConstraints({ (make) in - make.top.equalTo(self.messageButton.snp.bottom).offset(0) - make.centerX.equalTo(self.messageButton) - - }) - - return label - }() - - lazy var moreLabel: UILabel = { - let label = UILabel() - label.text = "more".localized - label.textColor = .white - label.textAlignment = .center - label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) - self.bottomView.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.centerX.equalTo(self.bottomView).offset(offsetX) - make.bottom.equalTo(self.declineButton.snp.top).offset(-2*offset) - }) - - return label - }() - - lazy var moreButton: UIButton = { - let button = UIButton() - button.setImage(#imageLiteral(resourceName: "ic_more_voice_call"), for: .normal) - button.addTarget(self, action: #selector(onMoreButtonPressed), for: .touchUpInside) - button.isEnabled = false - - self.bottomView.addSubview(button) - let offsetX = UIScreen.main.bounds.width / 3.0 - - button.snp.makeConstraints({ (make) in - make.height.equalTo(ConstraintConstants.buttonSize) - make.width.equalTo(ConstraintConstants.buttonSize) - make.centerX.equalTo(self.bottomView).offset(offsetX) - make.bottom.equalTo(self.moreLabel.snp.top).offset(0) - }) - - return button - }() - - lazy var heldCallTitle: UILabel = { - let label = UILabel() - label.text = "" - label.textColor = Constants.colors.lightGray.getColor() - label.textAlignment = .left - label.font = UIFont(name: Constants.fonts.regular, size: 13) - self.view.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.left.equalTo(self.view).offset(offset) - make.bottom.equalTo(self.bottomView.snp.top).offset(0) - }) - - return label - }() - - lazy var heldCallDescription: UILabel = { - let label = UILabel() - label.text = "" - label.textColor = Constants.colors.lightGray.getColor() - label.textAlignment = .right - label.font = UIFont(name: Constants.fonts.regular, size: 13) - self.view.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.right.equalTo(self.view).offset(-offset) - make.centerY.equalTo(self.heldCallTitle) - make.width.lessThanOrEqualTo(UIScreen.main.bounds.width/2 - CGFloat(offset)) - make.left.equalTo(self.heldCallTitle.snp.right).offset(offset) - }) - - return label - }() - - lazy var activeCallTitle: UILabel = { - let label = UILabel() - label.text = "" - label.textColor = Constants.colors.white.getColor() - label.textAlignment = .left - label.font = UIFont(name: Constants.fonts.regular, size: 13) - self.view.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.left.equalTo(self.view).offset(offset) - make.bottom.equalTo(self.heldCallTitle.snp.top).offset(0)//offset(-offset/2) - }) - - return label - }() - - lazy var activeCallDescription: UILabel = { - let label = UILabel() - label.text = "" - label.textColor = Constants.colors.white.getColor() - label.textAlignment = .right - label.font = UIFont(name: Constants.fonts.regular, size: 13) - self.view.addSubview(label) - - let offsetX = UIScreen.main.bounds.width / 3.0 - - label.snp.makeConstraints({ (make) in - make.right.equalTo(self.view).offset(-offset) - make.centerY.equalTo(self.activeCallTitle) - make.width.lessThanOrEqualTo(UIScreen.main.bounds.width/2 - CGFloat(offset)) - make.left.equalTo(self.activeCallTitle.snp.right).offset(offset) - }) - - return label - }() - - lazy var openCloseCallsButton: UIButton = { - let button = UIButton() - - let img = self.collapsed ? UIImage.init(named: "arrow_expand") : UIImage.init(named: "arrow_collapse") - button.setImage(img, for: .normal) - button.addTarget(self, action: #selector(onOpenCloseCallsButton), for: .touchUpInside) - - self.view.addSubview(button) - let offsetX = UIScreen.main.bounds.width / 3.0 - - button.snp.makeConstraints({ (make) in - make.height.equalTo(0)//(34) - make.width.equalTo(0)//(34) - make.centerX.equalTo(self.view) - make.bottom.equalTo(self.activeCallTitle.snp.top).offset(0)//offset(-offset/2) - }) - - return button + return page }() func setupInitialVisibility() { - - self.bottomView.isHidden = self.isIncomingCallRinging - self.bottomViewAcceptReject.isHidden = !self.isIncomingCallRinging - - // for all modes in view - self.nameLabel.isHidden = false - self.statusLabel.isHidden = false + callInProgressView.setup(self.isIncomingCallRinging, self.callInProgressMode, self.contact) + tapToSpeakView.setup() - self.heldCallTitle.isHidden = true - self.heldCallDescription.isHidden = true - self.activeCallTitle.isHidden = true - self.activeCallDescription.isHidden = true - self.openCloseCallsButton.isHidden = true - self.openCloseCallsButton.isEnabled = false - - // for all modes in bottom view - self.acceptButton.isHidden = false - self.rejectButton.isHidden = false - self.declineButton.isHidden = false - self.speakerButton.isHidden = false - self.speakerLabel.isHidden = false - self.cameraButton.isHidden = false - self.cameraLabel.isHidden = false - self.microphoneButton.isHidden = false - self.muteLabel.isHidden = false - self.messageButton.isHidden = false - self.chatLabel.isHidden = false - self.moreButton.isHidden = false - self.moreLabel.isHidden = false - - switch self.callInProgressMode! { - - case .oneToOneAudio: - self.myVideoView.isHidden = true - self.otherVideoView.isHidden = true - self.switchCameraButton.isHidden = true - self.backgroundImage.isHidden = false - self.backgroundGradientView.isHidden = false - self.backgroundImage.setImage(url: self.contact?.avatarUrl, placeHolder: UIImage(named: "ava_placeholder")) - self.view.bringSubview(toFront: self.backgroundImage) - self.view.insertSubview(self.backgroundGradientView, aboveSubview: self.backgroundImage) - self.view.backgroundColor = Constants.colors.grayForCallScreenTop.getColor() - statusLabel.text = "call_incoming".localized - - case .oneToOneVideo: - self.switchCameraButton.isHidden = true - self.myVideoView.isHidden = true - self.otherVideoView.isHidden = true - self.backgroundImage.isHidden = false - self.backgroundGradientView.isHidden = false - self.backgroundImage.setImage(url: self.contact?.avatarUrl, placeHolder: UIImage(named: "ava_placeholder")) - self.view.bringSubview(toFront: self.backgroundImage) - self.view.insertSubview(self.backgroundGradientView, aboveSubview: self.backgroundImage) - self.view.bringSubview(toFront: self.otherVideoView) - self.view.bringSubview(toFront: self.myVideoView) - self.view.bringSubview(toFront: self.switchCameraButton) - self.view.backgroundColor = Constants.colors.grayForCallScreenTop.getColor() - statusLabel.text = "call_incoming_video".localized - - case .groupAudio: - self.collectionView.isHidden = false - self.myVideoView.isHidden = true - self.otherVideoView.isHidden = true - self.switchCameraButton.isHidden = true - self.backgroundImage.isHidden = true - self.backgroundGradientView.isHidden = true - self.view.bringSubview(toFront: self.collectionView) - self.view.backgroundColor = Constants.colors.callBackground.getColor() - statusLabel.text = "call_incoming_audio_conference".localized - } - - self.view.bringSubview(toFront: self.bottomView) - self.view.bringSubview(toFront: self.bottomViewAcceptReject) - self.view.bringSubview(toFront: self.nameLabel) - self.view.bringSubview(toFront: self.statusLabel) + self.view.bringSubview(toFront: scrollView) + self.view.bringSubview(toFront: pageControl) + + goToSecondPage() + } + + func goToSecondPage() { + let x = UIScreen.main.bounds.size.width + scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: false) + pageControl.currentPage = 1; + pageControl.isHidden = (1 == pageControl.currentPage) + lastPageSelected = pageControl.currentPage } func updateTitle() { - var viewTitle:String = "" - + if let ctct = self.contact { - viewTitle = "\(ctct.names ?? "") \(ctct.surnames ?? "")" - } else if self.callInProgressMode == .groupAudio { if self.presenter != nil { if let room = RoomDAO.findRoom(by: self.roomId) { @@ -715,11 +224,10 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa } } - nameLabel.text = viewTitle + callInProgressView.nameLabel.text = viewTitle } func setupUI() { - updateTitle() } @@ -780,14 +288,11 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa //MARK: Collection View Delegates public func numberOfSections(in collectionView: UICollectionView) -> Int { - return 1 } //2 - func collectionView(_ collectionView: UICollectionView, - numberOfItemsInSection section: Int) -> Int { - + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { var rows:Int = dataSource.count if rows > 0 { @@ -799,7 +304,6 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa //3 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell:UICollectionViewCell? if 0 == indexPath.row { @@ -836,7 +340,6 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - let spacing : CGFloat = (collectionViewLayout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 0.0 let offsetIn:CGFloat = 5.0 let cellHeight = floor((collectionView.bounds.size.height - ((CGFloat(expectedRowsInCollectionView) - 1)*spacing))/CGFloat(expectedRowsInCollectionView)) @@ -857,45 +360,56 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa presenter.showMenuWith(groupCollectionCell:groupCollectionCell) } - //MARK: bottom view delegate - - @objc func declineButtonPressed() { + //MARK: CallInProgresView delegates + func declineButtonPressed() { presenter.declineCall() } - @objc func rejectButtonPressed() { - - self.bottomView.isHidden = false - self.bottomViewAcceptReject.isHidden = true + func rejectButtonPressed() { + callInProgressView.bottomView.isHidden = false + callInProgressView.bottomViewAcceptReject.isHidden = true self.isIncomingCallRinging = false presenter.rejectCall() } - @objc func acceptButtonPressed() { + func acceptButtonPressed() { - self.bottomView.isHidden = false - self.bottomViewAcceptReject.isHidden = true + callInProgressView.bottomView.isHidden = false + callInProgressView.bottomViewAcceptReject.isHidden = true self.isIncomingCallRinging = false presenter.acceptCall() } + + func microphoneButtonPressed() { + + toggleMicrophone() + } + + func toggleMicrophone() { + + let muteImage = (self.isMuted()) ? #imageLiteral(resourceName: "ic_unmute_voice_call") : #imageLiteral(resourceName: "ic_mute_voice_call") + callInProgressView.microphoneButton.setImage(muteImage, for: .normal) + + presenter.toggleMicrophone() + } - @objc func speakerButtonPressed() { + func speakerButtonPressed() { presenter.speakerAction() } func speakerUpdated(state: Speaker) { - speakerButton.isSelected = (state == .loud) + callInProgressView.speakerButton.isSelected = (state == .loud) + tapToSpeakView.leftButtonSpeakerView.isSelected = (state == .loud) } - @objc func messageButtonPressed() { - + func messageButtonPressed() { if .oneToOneVideo == self.callInProgressMode { - self.presenter.dettachLocalVideoPreview(inView: self.myVideoView) - self.presenter.removeRemoteVideoRenderer(inView: self.otherVideoView) + self.presenter.dettachLocalVideoPreview(inView: callInProgressView.myVideoView) + self.presenter.removeRemoteVideoRenderer(inView: callInProgressView.otherVideoView) } if let contact = self.contact { @@ -904,50 +418,32 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa presenter.messageAcion(with: roomId, isVideo: false) } - - } - - @objc func microphoneButtonPressed() { - - toggleMicrophone() - } - - func toggleMicrophone() { - - let muteImage = (self.isMuted()) ? #imageLiteral(resourceName: "ic_unmute_voice_call") : #imageLiteral(resourceName: "ic_mute_voice_call") - microphoneButton.setImage(muteImage, for: .normal) - - presenter.toggleMicrophone() } func isMuted()->Bool { - return presenter.isMuted() } func acceptAudioButtonPressed() { } - @objc func switchCameraButtonPressed() { + func switchCameraButtonPressed() { presenter.switchCamera() } func updateTime(text: String) { - if .oneToOneVideo == self.callInProgressMode { - statusLabel.text = "video_call_status".localized + " - \(text)" + callInProgressView.statusLabel.text = "video_call_status".localized + " - \(text)" } else { - statusLabel.text = "voice_call_status".localized + " - \(text)" + callInProgressView.statusLabel.text = "voice_call_status".localized + " - \(text)" } } func changeUIToIncall() { - self.setupUI() } func update(participants: [NYNCallParticipant]) { - dataSource.removeAllObjects() for mem in participants { @@ -968,62 +464,14 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa dataSource.add(mem) } - collectionView.reloadData() + callInProgressView.collectionView.reloadData() } - @objc func onCameraButtonPressed() { - + func onCameraButtonPressed() { LogService.log(topic: .callSystem) { return "onCameraButtonPressed"} self.presenter.cameraAction() } - @objc func onMoreButtonPressed() { - - - } - - @objc func onOpenCloseCallsButton() { - - self.openCloseCallsButton.snp.removeConstraints() - - UIView.animate(withDuration: 0.2, animations: { - - let alpha = self.collapsed ? 1.0 : 0.0 - self.activeCallTitle.alpha = CGFloat(alpha) - self.activeCallDescription.alpha = CGFloat(alpha) - self.heldCallTitle.alpha = CGFloat(alpha) - self.heldCallDescription.alpha = CGFloat(alpha) - - if self.collapsed { - - self.openCloseCallsButton.snp.makeConstraints({ (make) in - make.height.equalTo(34) - make.width.equalTo(34) - make.centerX.equalTo(self.view) - make.bottom.equalTo(self.activeCallTitle.snp.top).offset(-self.offset/2) - }) - - } else { - - self.openCloseCallsButton.snp.makeConstraints({ (make) in - make.height.equalTo(34) - make.width.equalTo(34) - make.centerX.equalTo(self.view) - make.bottom.equalTo(self.microphoneButton.snp.top).offset(-self.offset/2) - }) - } - - self.collapsed = !self.collapsed - let img = self.collapsed ? UIImage.init(named: "arrow_expand") : UIImage.init(named: "arrow_collapse") - self.openCloseCallsButton.setImage(img, for: .normal) - - self.view.layoutIfNeeded() - - }, completion: { _ in - - }) - } - func onPortOutButtonPressed() { let alertVC = UIAlertController(title: "voice_call_the_feature_currently_unavailable".localized, message: nil, preferredStyle: .alert) let okAction = UIAlertAction(title: "ok".localized, style: .cancel) { (action) in @@ -1082,12 +530,12 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa } func callConnecting() { - statusLabel.text = "call_connecting".localized + callInProgressView.statusLabel.text = "call_connecting".localized disableButtons() } func callRinging() { - statusLabel.text = "call_ringing".localized + callInProgressView.statusLabel.text = "call_ringing".localized disableButtons() } @@ -1097,56 +545,51 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa } private func enableButtons() { - - self.messageButton.isEnabled = (nil != self.contact) || (self.roomId.count > 0) - self.cameraButton.isEnabled = (.oneToOneVideo == self.callInProgressMode) - self.moreButton.isEnabled = true - self.speakerButton.isEnabled = true - self.microphoneButton.isEnabled = true + callInProgressView.messageButton.isEnabled = (nil != self.contact) || (self.roomId.count > 0) + callInProgressView.cameraButton.isEnabled = (.oneToOneVideo == self.callInProgressMode) + callInProgressView.moreButton.isEnabled = true + callInProgressView.speakerButton.isEnabled = true + callInProgressView.microphoneButton.isEnabled = true } private func disableButtons() { - - self.moreButton.isEnabled = false - self.cameraButton.isEnabled = false - self.messageButton.isEnabled = false - self.speakerButton.isEnabled = false - self.microphoneButton.isEnabled = false + callInProgressView.moreButton.isEnabled = false + callInProgressView.cameraButton.isEnabled = false + callInProgressView.messageButton.isEnabled = false + callInProgressView.speakerButton.isEnabled = false + callInProgressView.microphoneButton.isEnabled = false } private func handleDidAddRemoteVideoStream() { + callInProgressView.otherVideoView.isHidden = false + callInProgressView.backgroundImage.isHidden = true - self.otherVideoView.isHidden = false - self.backgroundImage.isHidden = true - - self.presenter.addRemoteVideoRenderer(inView: self.otherVideoView); + self.presenter.addRemoteVideoRenderer(inView: callInProgressView.otherVideoView); } private func handleDidRemoveRemoteVideoStream() { - self.otherVideoView.isHidden = true - self.backgroundImage.isHidden = false + callInProgressView.otherVideoView.isHidden = true + callInProgressView.backgroundImage.isHidden = false } private func handleDidStartLocalCapturer() { - - self.myVideoView.isHidden = false - self.view.insertSubview(self.myVideoView, aboveSubview: self.otherVideoView) - self.switchCameraButton.isHidden = false + callInProgressView.myVideoView.isHidden = false + callInProgressView.insertSubview(callInProgressView.myVideoView, aboveSubview: callInProgressView.otherVideoView) + callInProgressView.switchCameraButton.isHidden = false - self.cameraButton.setImage( #imageLiteral(resourceName: "ic_video_on_voice_call") , for: .normal) + callInProgressView.cameraButton.setImage( #imageLiteral(resourceName: "ic_video_on_voice_call") , for: .normal) - self.presenter.attachLocalVideoPreview(inView: self.myVideoView); + self.presenter.attachLocalVideoPreview(inView: callInProgressView.myVideoView); } private func handleDidStopLocalCapturer() { - - self.myVideoView.isHidden = true - self.view.sendSubview(toBack: self.myVideoView) - self.switchCameraButton.isHidden = true + callInProgressView.myVideoView.isHidden = true + callInProgressView.sendSubview(toBack: callInProgressView.myVideoView) + callInProgressView.switchCameraButton.isHidden = true - self.cameraButton.setImage( #imageLiteral(resourceName: "ic_video_off_voice_call") , for: .normal) + callInProgressView.cameraButton.setImage( #imageLiteral(resourceName: "ic_video_off_voice_call") , for: .normal) - self.presenter.dettachLocalVideoPreview(inView: self.myVideoView); + self.presenter.dettachLocalVideoPreview(inView: callInProgressView.myVideoView); } private func isCameraRunning() -> Bool { @@ -1156,4 +599,74 @@ class CallInProgressViewController: BaseVC, CallInProgressViewProtocol, BottomCa return presenter.isCameraRunning() } + + +// MARK Tap To Speak Delegates + func tapToSpeakButtonPressed() { + if tapToSpeakView.tapToSpeakButton.isSelected { + if isMuted() { + toggleMicrophone() + } + + } else { + if !isMuted() { + toggleMicrophone() + } + } + } + + func tapToSpeakOutsideButtonPressed() { + if !isMuted() { + toggleMicrophone() + } + } + + func rightButtonSpeakerViewPressed () { + declineButtonPressed() + } + + func leftButtonSpeakerViewPressed () { + presenter.speakerAction() + } + +// MARK UIScrollView Delegates + func scrollViewDidScroll(_ scrollView: UIScrollView) { + let pageWidth = UIScreen.main.bounds.size.width + let fractionalPage = self.scrollView.contentOffset.x / pageWidth + let page = lround(Double(fractionalPage)) + self.pageControl.currentPage = page + + self.pageControl.isHidden = (1 == page) + } + + func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + let pageNumber = roundf(Float(scrollView.contentOffset.x / (UIScreen.main.bounds.size.width))); + + if lastPageSelected == 1, 0 == pageNumber { + tapToSpeakView.tapToSpeakButton.isSelected = false + tapToSpeakView.updateButtonTapToSpeak() + + tapToSpeakView.isMutedMicrStateWhenAppearing = isMuted() + + if !isMuted() { + toggleMicrophone() + } + } else if lastPageSelected == 0, 1 == pageNumber { + + if tapToSpeakView.isMutedMicrStateWhenAppearing != isMuted() { + toggleMicrophone() + } + } + + pageControl.currentPage = Int(pageNumber); + lastPageSelected = pageControl.currentPage + } + +// MARK Page Control Action + + @objc func changePage() { + let x = CGFloat(pageControl.currentPage) * UIScreen.main.bounds.size.width + scrollView.setContentOffset(CGPoint(x: x, y: 0), animated: true) + lastPageSelected = pageControl.currentPage + } } diff --git a/Nynja/Modules/Call/View/CallInProgressView.swift b/Nynja/Modules/Call/View/CallInProgressView.swift new file mode 100644 index 0000000000000000000000000000000000000000..575db437a34914183f345c6656c56ce69e70cfa6 --- /dev/null +++ b/Nynja/Modules/Call/View/CallInProgressView.swift @@ -0,0 +1,720 @@ +// +// CallInProgressView.swift +// Nynja +// +// Created by Bozhko Terziev on 10.09.18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import UIKit + +protocol CallInProgressViewDelegate: class { + func switchCameraButtonPressed() + func declineButtonPressed() + func rejectButtonPressed() + func acceptButtonPressed() + func microphoneButtonPressed() + func speakerButtonPressed() + func messageButtonPressed() + func onCameraButtonPressed() + func onMoreButtonPressed() +} + +extension CallInProgressViewDelegate { + func switchCameraButtonPressed(){} + func declineButtonPressed(){} + func rejectButtonPressed(){} + func acceptButtonPressed(){} + func microphoneButtonPressed(){} + func speakerButtonPressed(){} + func messageButtonPressed(){} + func onCameraButtonPressed(){} + func onMoreButtonPressed(){} +} + +class CallInProgressView: UIView { + weak var delegate: CallInProgressViewDelegate? + + let offset: Float = 10.0 + let bottomViewHeight: Float = 188.0 + let labelNameHeight: Float = 40.0 + let labelStatusHeight: Float = 30.0 + let middleGVHeight: Float = 100.0 + + var isMuted: Bool = false + var collapsed: Bool = false + var isCameraRunning: Bool = false + + private struct ConstraintConstants { + + static let buttonSize: CGFloat = 44.0 + + static let bottomOffset: CGFloat = 16.0 + + static let labelNameFontSize: CGFloat = 22.0 + static let labelStatusFontSize: CGFloat = 16.0 + + static let labelsFontSize: CGFloat = 11.0 + static let minSectionHeight: CGFloat = 83.0 + + static let gradientHeight: CGFloat = 144.0 + + static let declineButtonSize:CGFloat = 68.0 + + static let myVideoViewWidth:CGFloat = 72.0 + static let myVideoViewHeight:CGFloat = 115.0 + static let myVideoViewLeftInset:CGFloat = 16.0 + static let myVideoViewBottomInset:CGFloat = 20.0 + } + + lazy var backgroundGradientView: UIView = { + + let view = GradientView(colors: [Constants.colors.callGradientStart.getColor(), + Constants.colors.callGradientEnd.getColor()]) + self.addSubview(view) + view.snp.makeConstraints({ (make) in + + make.top.left.right.equalTo(self) + make.height.equalTo(ConstraintConstants.gradientHeight.adjustedByWidth) + }) + + return view + }() + + lazy var backgroundImage: UIImageView = { + + let img = UIImageView() + img.isUserInteractionEnabled = true + img.contentMode = .scaleAspectFill + img.clipsToBounds = true + img.backgroundColor = Constants.colors.callBackground.getColor() + self.addSubview(img) + + img.snp.makeConstraints({ (make) in + make.top.left.right.equalTo(self) + make.bottom.equalTo(self.bottomView.snp.top).offset(-offset/2) + }) + return img + }() + + lazy var otherVideoView: UIView = { + + let view = UIView() + view.isUserInteractionEnabled = true + view.backgroundColor = self.backgroundColor + self.addSubview(view) + + view.snp.makeConstraints({ (make) in + make.top.left.right.equalTo(self) + make.bottom.equalTo(self.bottomView.snp.top).offset(-offset/2) + }) + return view + }() + + lazy var myVideoView: UIView = { + + let view = UIView() + view.isUserInteractionEnabled = true + view.backgroundColor = .clear + self.addSubview(view) + + view.snp.makeConstraints({ (make) in + make.left.equalTo(self).offset(ConstraintConstants.myVideoViewLeftInset.adjustedByWidth) + make.bottom.equalTo(self.otherVideoView.snp.bottom).offset(-ConstraintConstants.myVideoViewBottomInset.adjustedByWidth) + make.width.equalTo(ConstraintConstants.myVideoViewWidth.adjustedByWidth) + make.height.equalTo(ConstraintConstants.myVideoViewHeight.adjustedByWidth) + }) + return view + }() + + lazy var switchCameraButton: UIButton = { + + let btn = UIButton() + let img = #imageLiteral(resourceName: "switch_camera") + btn.backgroundColor = .clear + btn.setImage(img, for: .normal) + self.addSubview(btn) + + btn.addTarget(self, action: #selector(switchCameraButtonPressed), for: .touchUpInside) + + btn.snp.makeConstraints({ (make) in + make.right.equalTo(self).offset(-offset) + make.bottom.equalTo(self.otherVideoView.snp.bottom).offset(-offset) + make.width.height.equalTo(44) + }) + return btn + }() + + lazy var collectionView: UICollectionView = { + let layout = UICollectionViewFlowLayout() + layout.scrollDirection = .vertical + layout.minimumLineSpacing = 0 + layout.minimumInteritemSpacing = 0 + let cv = GroupCollectionView(frame: .zero, collectionViewLayout: layout) + cv.isUserInteractionEnabled = true + self.addSubview(cv) + cv.backgroundColor = Constants.colors.callBackground.getColor() + + cv.register(GroupCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: GroupCollectionViewCell.self)) + cv.register(GroupAddParticipantsCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: GroupAddParticipantsCollectionViewCell.self)) + + cv.snp.makeConstraints({ (make) in + make.top.equalTo(self.statusLabel.snp.bottom).offset(offset) + make.left.right.equalTo(self) + make.bottom.equalTo(self.openCloseCallsButton.snp.top).offset(-offset/2) + + }) + return cv + }() + + lazy var nameLabel: UILabel = { + let scwidth = UIScreen.main.bounds.width + let lbl = UILabel() + lbl.textAlignment = .center + lbl.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelNameFontSize) + lbl.textColor = Constants.colors.white.getColor() + lbl.numberOfLines = 1 + lbl.baselineAdjustment = .alignCenters + lbl.lineBreakMode = .byTruncatingTail + self.addSubview(lbl) + + lbl.snp.makeConstraints({ (make) in + make.top.equalTo(self).offset(6*offset) + make.left.right.equalTo(self).offset(offset) + make.height.equalTo(lbl.font.lineHeight) + }) + + return lbl + }() + + lazy var statusLabel: UILabel = { + let scwidth = UIScreen.main.bounds.width + let lbl = UILabel() + lbl.textAlignment = .center + lbl.font = UIFont(name: Constants.fonts.regular, size: ConstraintConstants.labelStatusFontSize) + lbl.textColor = Constants.colors.white.getColor() + lbl.backgroundColor = .clear + lbl.numberOfLines = 1 + lbl.adjustsFontSizeToFitWidth = true + lbl.baselineAdjustment = .alignCenters + lbl.lineBreakMode = .byClipping + self.addSubview(lbl) + + lbl.snp.makeConstraints({ (make) in + make.top.equalTo(self.nameLabel.snp.bottom).offset(offset) + make.left.right.equalTo(self).offset(offset) + make.height.equalTo(lbl.font.lineHeight) + }) + + return lbl + }() + + lazy var bottomView : UIView = { + + let view = UIView() + view.isUserInteractionEnabled = true + view.backgroundColor = .clear + self.addSubview(view) + + view.snp.makeConstraints({ (make) in + make.bottom.left.right.equalTo(self) + make.height.equalTo(self.bottomViewHeight) + }) + + return view + }() + + lazy var bottomViewAcceptReject : UIView = { + + let view = UIView() + view.isUserInteractionEnabled = true + view.backgroundColor = .clear + self.addSubview(view) + + view.snp.makeConstraints({ (make) in + make.bottom.left.right.equalTo(self) + make.height.equalTo(self.bottomViewHeight) + }) + + return view + }() + + lazy var rejectButton : UIButton = { + let btn = UIButton() + let img = UIImage.init(named:"ic_decline_call") + btn.backgroundColor = .clear + btn.setImage(img, for: .normal) + self.bottomViewAcceptReject.addSubview(btn) + btn.addTarget(self, action: #selector(rejectButtonPressed), for: .touchUpInside) + let center = UIScreen.main.bounds.width / 3.0 + + btn.snp.makeConstraints({ (make) in + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.centerY.equalTo(self.bottomViewAcceptReject.snp.centerY) + make.centerX.equalTo(self).offset(-center + ConstraintConstants.declineButtonSize/2) + }) + return btn + }() + + lazy var acceptButton : UIButton = { + let btn = UIButton() + let img = UIImage.init(named:"ic_accept_call_big") + btn.backgroundColor = .clear + btn.setImage(img, for: .normal) + self.bottomViewAcceptReject.addSubview(btn) + btn.addTarget(self, action: #selector(acceptButtonPressed), for: .touchUpInside) + let center = UIScreen.main.bounds.width / 3.0 + + btn.snp.makeConstraints({ (make) in + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.centerY.equalTo(self.bottomViewAcceptReject.snp.centerY) + make.centerX.equalTo(self).offset(center - ConstraintConstants.declineButtonSize/2) + }) + return btn + }() + + lazy var declineButton : UIButton = { + let btn = UIButton() + let img = UIImage.init(named:"ic_decline_call") + btn.backgroundColor = .clear + btn.setImage(img, for: .normal) + self.bottomView.addSubview(btn) + btn.addTarget(self, action: #selector(declineButtonPressed), for: .touchUpInside) + + btn.snp.makeConstraints({ (make) in + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.width.height.equalTo(ConstraintConstants.declineButtonSize) + make.bottom.equalTo(self).offset(-ConstraintConstants.bottomOffset) + make.centerX.equalTo(self) + }) + return btn + }() + + lazy var speakerButton : UIButton = { + + let btn = UIButton() + + AudioManager.sharedInstance.speaker = .soft + + btn.setImage(#imageLiteral(resourceName: "ic_speaker_off"), for: .normal) + btn.setImage(#imageLiteral(resourceName: "ic_speaker_on"), for: .selected) + btn.isSelected = (AudioManager.sharedInstance.speaker == .loud) + + btn.layer.masksToBounds = true + btn.isEnabled = false + self.bottomView.addSubview(btn) + let offsetX = UIScreen.main.bounds.width / 3.0 + btn.addTarget(self, action: #selector(speakerButtonPressed), for: .touchUpInside) + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.buttonSize) + make.height.equalTo(ConstraintConstants.buttonSize) + make.centerX.equalTo(self.bottomView).offset(-offsetX) + make.centerY.equalTo(self.declineButton.snp.centerY) + }) + return btn + }() + + lazy var speakerLabel: UILabel = { + let label = UILabel() + label.text = "speakerphone".localized + label.textColor = .white + label.textAlignment = .center + label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) + self.bottomView.addSubview(label) + + label.snp.makeConstraints({ (make) in + make.top.equalTo(self.speakerButton.snp.bottom).offset(0) + make.centerX.equalTo(self.speakerButton) + }) + + return label + }() + + lazy var cameraLabel: UILabel = { + let label = UILabel() + label.text = "turn_on_video".localized + label.textColor = .white + label.textAlignment = .center + label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) + self.bottomView.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.centerX.equalTo(self).offset(-offsetX) + make.bottom.equalTo(self.declineButton.snp.top).offset(-2*offset) + }) + + return label + }() + + lazy var cameraButton: UIButton = { + let button = UIButton() + let image = self.isCameraRunning ? #imageLiteral(resourceName: "ic_video_on_voice_call") : #imageLiteral(resourceName: "ic_video_off_voice_call") + button.setImage(image, for: .normal) + button.addTarget(self, action: #selector(onCameraButtonPressed), for: .touchUpInside) + button.isEnabled = false + self.bottomView.addSubview(button) + let offsetX = UIScreen.main.bounds.width / 3.0 + + button.snp.makeConstraints({ (make) in + make.height.equalTo(ConstraintConstants.buttonSize) + make.width.equalTo(ConstraintConstants.buttonSize) + make.centerX.equalTo(self.bottomView).offset(-offsetX) + make.bottom.equalTo(self.cameraLabel.snp.top).offset(0) + }) + + return button + }() + + lazy var microphoneButton : UIButton = { + let btn = UIButton() + let muteImage = self.isMuted ? #imageLiteral(resourceName: "ic_mute_voice_call"): #imageLiteral(resourceName: "ic_unmute_voice_call") + btn.setImage(muteImage, for: .normal) + btn.isEnabled = false + btn.layer.masksToBounds = true + self.bottomView.addSubview(btn) + btn.addTarget(self, action: #selector(microphoneButtonPressed), for: .touchUpInside) + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.buttonSize) + make.height.equalTo(ConstraintConstants.buttonSize) + make.centerY.equalTo(self.cameraButton.snp.centerY).offset(0) + make.centerX.equalTo(self.bottomView) + }) + return btn + }() + + lazy var muteLabel: UILabel = { + let label = UILabel() + label.text = "mute_call".localized + label.textColor = .white + label.textAlignment = .center + label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) + self.bottomView.addSubview(label) + + label.snp.makeConstraints({ (make) in + make.centerY.equalTo(self.cameraLabel.snp.centerY).offset(0) + make.centerX.equalTo(self.microphoneButton) + }) + + return label + }() + + lazy var messageButton : UIButton = { + let btn = UIButton() + let img = #imageLiteral(resourceName: "ic_go_to_chat") + btn.setImage(img, for: .normal) + self.bottomView.addSubview(btn) + let offsetX = UIScreen.main.bounds.width / 3.0 + btn.addTarget(self, action: #selector(messageButtonPressed), for: .touchUpInside) + btn.isEnabled = false + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.buttonSize) + make.height.equalTo(ConstraintConstants.buttonSize) + make.centerX.equalTo(self.bottomView).offset(offsetX) + make.centerY.equalTo(self.declineButton.snp.centerY) + }) + return btn + }() + + lazy var chatLabel: UILabel = { + let label = UILabel() + label.text = "return_to_chat_from_call".localized + label.textColor = .white + label.textAlignment = .center + label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) + self.bottomView.addSubview(label) + + label.snp.makeConstraints({ (make) in + make.top.equalTo(self.messageButton.snp.bottom).offset(0) + make.centerX.equalTo(self.messageButton) + + }) + + return label + }() + + lazy var moreLabel: UILabel = { + let label = UILabel() + label.text = "more".localized + label.textColor = .white + label.textAlignment = .center + label.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelsFontSize) + self.bottomView.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.centerX.equalTo(self.bottomView).offset(offsetX) + make.bottom.equalTo(self.declineButton.snp.top).offset(-2*offset) + }) + + return label + }() + + lazy var moreButton: UIButton = { + let button = UIButton() + button.setImage(#imageLiteral(resourceName: "ic_more_voice_call"), for: .normal) + button.addTarget(self, action: #selector(onMoreButtonPressed), for: .touchUpInside) + button.isEnabled = false + + self.bottomView.addSubview(button) + let offsetX = UIScreen.main.bounds.width / 3.0 + + button.snp.makeConstraints({ (make) in + make.height.equalTo(ConstraintConstants.buttonSize) + make.width.equalTo(ConstraintConstants.buttonSize) + make.centerX.equalTo(self.bottomView).offset(offsetX) + make.bottom.equalTo(self.moreLabel.snp.top).offset(0) + }) + + return button + }() + + lazy var heldCallTitle: UILabel = { + let label = UILabel() + label.text = "" + label.textColor = Constants.colors.lightGray.getColor() + label.textAlignment = .left + label.font = UIFont(name: Constants.fonts.regular, size: 13) + self.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.left.equalTo(self).offset(offset) + make.bottom.equalTo(self.bottomView.snp.top).offset(0) + }) + + return label + }() + + lazy var heldCallDescription: UILabel = { + let label = UILabel() + label.text = "" + label.textColor = Constants.colors.lightGray.getColor() + label.textAlignment = .right + label.font = UIFont(name: Constants.fonts.regular, size: 13) + self.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.right.equalTo(self).offset(-offset) + make.centerY.equalTo(self.heldCallTitle) + make.width.lessThanOrEqualTo(UIScreen.main.bounds.width/2 - CGFloat(offset)) + make.left.equalTo(self.heldCallTitle.snp.right).offset(offset) + }) + + return label + }() + + lazy var activeCallTitle: UILabel = { + let label = UILabel() + label.text = "" + label.textColor = Constants.colors.white.getColor() + label.textAlignment = .left + label.font = UIFont(name: Constants.fonts.regular, size: 13) + self.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.left.equalTo(self).offset(offset) + make.bottom.equalTo(self.heldCallTitle.snp.top).offset(0)//offset(-offset/2) + }) + + return label + }() + + lazy var activeCallDescription: UILabel = { + let label = UILabel() + label.text = "" + label.textColor = Constants.colors.white.getColor() + label.textAlignment = .right + label.font = UIFont(name: Constants.fonts.regular, size: 13) + self.addSubview(label) + + let offsetX = UIScreen.main.bounds.width / 3.0 + + label.snp.makeConstraints({ (make) in + make.right.equalTo(self).offset(-offset) + make.centerY.equalTo(self.activeCallTitle) + make.width.lessThanOrEqualTo(UIScreen.main.bounds.width/2 - CGFloat(offset)) + make.left.equalTo(self.activeCallTitle.snp.right).offset(offset) + }) + + return label + }() + + lazy var openCloseCallsButton: UIButton = { + let button = UIButton() + + let img = self.collapsed ? UIImage.init(named: "arrow_expand") : UIImage.init(named: "arrow_collapse") + button.setImage(img, for: .normal) + button.addTarget(self, action: #selector(onOpenCloseCallsButton), for: .touchUpInside) + + self.addSubview(button) + let offsetX = UIScreen.main.bounds.width / 3.0 + + button.snp.makeConstraints({ (make) in + make.height.equalTo(0)//(34) + make.width.equalTo(0)//(34) + make.centerX.equalTo(self) + make.bottom.equalTo(self.activeCallTitle.snp.top).offset(0)//offset(-offset/2) + }) + + return button + }() + + func setup(_ isIncommingCallRinging:Bool, _ callMode:CallInProgressMode, _ contact:Contact?) { + + self.bottomView.isHidden = isIncommingCallRinging + self.bottomViewAcceptReject.isHidden = !isIncommingCallRinging + + // for all modes in view + self.nameLabel.isHidden = false + self.statusLabel.isHidden = false + + self.heldCallTitle.isHidden = true + self.heldCallDescription.isHidden = true + self.activeCallTitle.isHidden = true + self.activeCallDescription.isHidden = true + self.openCloseCallsButton.isHidden = true + self.openCloseCallsButton.isEnabled = false + + // for all modes in bottom view + self.acceptButton.isHidden = false + self.rejectButton.isHidden = false + self.declineButton.isHidden = false + self.speakerButton.isHidden = false + self.speakerLabel.isHidden = false + self.cameraButton.isHidden = false + self.cameraLabel.isHidden = false + self.microphoneButton.isHidden = false + self.muteLabel.isHidden = false + self.messageButton.isHidden = false + self.chatLabel.isHidden = false + self.moreButton.isHidden = false + self.moreLabel.isHidden = false + self.myVideoView.isHidden = true + self.otherVideoView.isHidden = true + self.switchCameraButton.isHidden = true + + switch callMode { + + case .oneToOneAudio: + self.backgroundImage.isHidden = false + self.backgroundGradientView.isHidden = false + self.backgroundImage.setImage(url: contact?.avatarUrl, placeHolder: UIImage(named: "ava_placeholder")) + self.bringSubview(toFront: self.backgroundImage) + self.insertSubview(self.backgroundGradientView, aboveSubview: self.backgroundImage) + self.backgroundColor = Constants.colors.callBackground.getColor() + self.statusLabel.text = "call_incoming".localized + + case .oneToOneVideo: + self.backgroundImage.isHidden = false + self.backgroundGradientView.isHidden = false + self.backgroundImage.setImage(url: contact?.avatarUrl, placeHolder: UIImage(named: "ava_placeholder")) + self.bringSubview(toFront: self.backgroundImage) + self.insertSubview(self.backgroundGradientView, aboveSubview: self.backgroundImage) + self.bringSubview(toFront: self.otherVideoView) + self.bringSubview(toFront: self.myVideoView) + self.bringSubview(toFront: self.switchCameraButton) + self.backgroundColor = Constants.colors.callBackground.getColor() + self.statusLabel.text = "call_incoming_video".localized + + case .groupAudio: + self.collectionView.isHidden = false + self.backgroundImage.isHidden = true + self.backgroundGradientView.isHidden = true + self.bringSubview(toFront: self.collectionView) + self.backgroundColor = Constants.colors.callBackground.getColor() + self.statusLabel.text = "call_incoming_audio_conference".localized + } + + self.bringSubview(toFront: self.bottomView) + self.bringSubview(toFront: self.bottomViewAcceptReject) + self.bringSubview(toFront: self.nameLabel) + self.bringSubview(toFront: self.statusLabel) + } + + @objc func switchCameraButtonPressed () { + self.delegate?.switchCameraButtonPressed() + } + + @objc func rejectButtonPressed () { + self.delegate?.rejectButtonPressed() + } + + @objc func declineButtonPressed () { + self.delegate?.declineButtonPressed() + } + + @objc func acceptButtonPressed () { + self.delegate?.acceptButtonPressed() + } + + @objc func microphoneButtonPressed () { + self.delegate?.microphoneButtonPressed() + } + + @objc func speakerButtonPressed () { + self.delegate?.speakerButtonPressed() + } + + @objc func messageButtonPressed () { + self.delegate?.messageButtonPressed() + } + + @objc func onCameraButtonPressed () { + self.delegate?.onCameraButtonPressed() + } + + @objc func onMoreButtonPressed () { + self.delegate?.onMoreButtonPressed() + } + + @objc func onOpenCloseCallsButton () { + self.openCloseCallsButton.snp.removeConstraints() + + UIView.animate(withDuration: 0.2, animations: { + + let alpha = self.collapsed ? 1.0 : 0.0 + self.activeCallTitle.alpha = CGFloat(alpha) + self.activeCallDescription.alpha = CGFloat(alpha) + self.heldCallTitle.alpha = CGFloat(alpha) + self.heldCallDescription.alpha = CGFloat(alpha) + + if self.collapsed { + self.openCloseCallsButton.snp.makeConstraints({ (make) in + make.height.equalTo(34) + make.width.equalTo(34) + make.centerX.equalTo(self) + make.bottom.equalTo(self.activeCallTitle.snp.top).offset(-self.offset/2) + }) + } else { + + self.openCloseCallsButton.snp.makeConstraints({ (make) in + make.height.equalTo(34) + make.width.equalTo(34) + make.centerX.equalTo(self) + make.bottom.equalTo(self.microphoneButton.snp.top).offset(-self.offset/2) + }) + } + + self.collapsed = !self.collapsed + let img = self.collapsed ? UIImage.init(named: "arrow_expand") : UIImage.init(named: "arrow_collapse") + self.openCloseCallsButton.setImage(img, for: .normal) + + self.layoutIfNeeded() + }, completion: { _ in + + }) + } +} diff --git a/Nynja/Modules/Call/View/TapToSpeakView.swift b/Nynja/Modules/Call/View/TapToSpeakView.swift new file mode 100644 index 0000000000000000000000000000000000000000..9389d452e46ffcb13cc0d568c82aafd833cbf2ad --- /dev/null +++ b/Nynja/Modules/Call/View/TapToSpeakView.swift @@ -0,0 +1,232 @@ +// +// TapToSpeakView.swift +// Nynja +// +// Created by Bozhko Terziev on 10.09.18. +// Copyright © 2018 TecSynt Solutions. All rights reserved. +// + +import UIKit + +protocol TapToSpeakViewDelegate: class { + + func tapToSpeakButtonPressed() + func tapToSpeakOutsideButtonPressed() + func rightButtonSpeakerViewPressed() + func leftButtonSpeakerViewPressed() +} + +class TapToSpeakView: UIView { + + weak var delegate: TapToSpeakViewDelegate? + + private struct ConstraintConstants { + + static let offset: CGFloat = 10.0 + + static let labelTitleFontSize: CGFloat = 19.0 + static let labelSpeakerViewFontSize: CGFloat = 17.0 + static let buttonSpeakerFontSize: CGFloat = 20.0 + + static let buttonSize: CGFloat = 44.0 + + static let speakerButtonSize: CGFloat = 130.0 + } + + let tagButtonTapToSpeak = 12321 + var isMutedMicrStateWhenAppearing = false + + lazy var leftButtonSpeakerView : UIButton = { + + let btn = UIButton() + + AudioManager.sharedInstance.speaker = .soft + + btn.setImage(#imageLiteral(resourceName: "ic_speaker_off"), for: .normal) + btn.setImage(#imageLiteral(resourceName: "ic_speaker_on"), for: .selected) + btn.isSelected = (AudioManager.sharedInstance.speaker == .loud) + + btn.layer.masksToBounds = true + self.addSubview(btn) + + btn.addTarget(self, action: #selector(leftButtonSpeakerViewPressed), for: .touchUpInside) + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.buttonSize) + make.height.equalTo(ConstraintConstants.buttonSize) + make.top.equalTo(self).offset(3*ConstraintConstants.offset) + make.left.equalTo(self).offset(ConstraintConstants.offset) + }) + return btn + }() + + lazy var titleSpeakerView: UILabel = { + let lbl = UILabel() + lbl.textAlignment = .center + lbl.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelTitleFontSize.adjustedByHeight) + lbl.textColor = Constants.colors.white.getColor() + lbl.numberOfLines = 1 + lbl.baselineAdjustment = .alignCenters + lbl.lineBreakMode = .byTruncatingTail + lbl.text = "hold_to_speak_title".localized + self.addSubview(lbl) + + lbl.snp.makeConstraints({ (make) in + make.top.equalTo(4*ConstraintConstants.offset) + make.centerX.equalTo(self) + }) + + return lbl + }() + + lazy var rightButtonSpeakerView : UIButton = { + + let btn = UIButton() + + AudioManager.sharedInstance.speaker = .soft + + btn.setTitle("hold_to_speak_button_leave".localized, for: .normal) + btn.setTitleColor(Constants.colors.red.getColor(), for: .normal) + btn.setTitleColor(Constants.colors.darkRed.getColor(), for: .selected) + btn.setTitleColor(Constants.colors.darkRed.getColor(), for: .highlighted) + + btn.layer.masksToBounds = true + self.addSubview(btn) + + btn.addTarget(self, action: #selector(rightButtonSpeakerViewPressed), for: .touchDown) + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.buttonSize + ConstraintConstants.offset) + make.height.equalTo(ConstraintConstants.buttonSize) + make.top.equalTo(self).offset(3*ConstraintConstants.offset) + make.right.equalTo(self).offset(-ConstraintConstants.offset) + }) + return btn + }() + + lazy var separatorSpeakView : UIView = { + + let view = UIView() + view.backgroundColor = Constants.colors.separatorGrayColor.getColor() + self.addSubview(view) + + view.snp.makeConstraints({ (make) in + make.left.right.equalToSuperview() + make.height.equalTo(1.0) + make.top.equalTo(self.titleSpeakerView.snp.bottom).offset(2*ConstraintConstants.offset) + }) + + return view + }() + + lazy var labelTapToSpeakView : UILabel = { + + let lbl = UILabel() + lbl.textAlignment = .center + lbl.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.labelSpeakerViewFontSize.adjustedByHeight) + lbl.textColor = Constants.colors.white.getColor() + lbl.numberOfLines = 1 + lbl.baselineAdjustment = .alignCenters + lbl.lineBreakMode = .byTruncatingTail + lbl.text = tapToSpeakButton.isSelected ? "hold_to_speak_label_micr_on".localized : "hold_to_speak_label_micr_off".localized + self.addSubview(lbl) + + lbl.snp.makeConstraints({ (make) in + make.bottom.equalTo(self.tapToSpeakButton.snp.top).offset(-3*ConstraintConstants.offset) + make.centerX.equalTo(self) + }) + + return lbl + }() + + lazy var tapToSpeakButton : UIButton = { + + let btn = UIButton() + + AudioManager.sharedInstance.speaker = .soft + + btn.setTitleColor(btn.isSelected ? .black : .white , for: .normal) + btn.backgroundColor = btn.isSelected ? .white : .clear + btn.setTitle(btn.isSelected ? "hold_to_speak_button_done".localized : "hold_to_speak_button".localized, for: .normal) + btn.titleLabel?.font = UIFont(name: Constants.fonts.medium, size: ConstraintConstants.buttonSpeakerFontSize.adjustedByHeight) + btn.titleLabel?.numberOfLines = 2 + btn.titleLabel?.contentMode = .center + btn.titleLabel?.textAlignment = .center + btn.layer.masksToBounds = true + btn.tag = tagButtonTapToSpeak + + btn.layer.cornerRadius = CGFloat(ConstraintConstants.speakerButtonSize.adjustedByHeight/2) + btn.clipsToBounds = true + btn.layer.borderColor = Constants.colors.white.getColor().cgColor + btn.layer.borderWidth = 1.0 + + self.addSubview(btn) + + btn.addTarget(self, action: #selector(tapToSpeakPressed), for: .touchDown) + btn.addTarget(self, action: #selector(tapToSpeakPressedRemoved), for: .touchUpInside) + btn.addTarget(self, action: #selector(tapToSpeakPressedRemoved), for: .touchUpOutside) + + + btn.snp.makeConstraints({ (make) in + make.width.equalTo(ConstraintConstants.speakerButtonSize.adjustedByHeight) + make.height.equalTo(ConstraintConstants.speakerButtonSize.adjustedByHeight) + make.centerX.equalTo(self) + make.centerY.equalTo(self) + }) + return btn + }() + + func setup() { + self.leftButtonSpeakerView.isHidden = false + self.rightButtonSpeakerView.isHidden = false + self.titleSpeakerView.isHidden = false + self.tapToSpeakButton.isHidden = false + self.separatorSpeakView.isHidden = false + self.labelTapToSpeakView.isHidden = false + } + + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + let touch = touches.first + + let tag = touch?.view?.tag + + if tag != tagButtonTapToSpeak { + } + } + + func tapToSpeakOutsideButtonPressed() { + if tapToSpeakButton.isSelected { + + tapToSpeakButton.isSelected = false + updateButtonTapToSpeak() + self.delegate?.tapToSpeakOutsideButtonPressed() + } + } + + func updateButtonTapToSpeak() { + tapToSpeakButton.setTitleColor(tapToSpeakButton.isSelected ? .black : .white , for: .normal) + tapToSpeakButton.backgroundColor = tapToSpeakButton.isSelected ? .white : .clear + tapToSpeakButton.setTitle(tapToSpeakButton.isSelected ? "hold_to_speak_button_done".localized : "hold_to_speak_button".localized, for: .normal) + labelTapToSpeakView.text = tapToSpeakButton.isSelected ? "hold_to_speak_label_micr_on".localized : "hold_to_speak_label_micr_off".localized + } + + @objc func leftButtonSpeakerViewPressed() { + self.delegate?.leftButtonSpeakerViewPressed() + } + + @objc func rightButtonSpeakerViewPressed() { + self.delegate?.rightButtonSpeakerViewPressed() + } + + @objc func tapToSpeakPressedRemoved() { + tapToSpeakButton.isSelected = !tapToSpeakButton.isSelected + updateButtonTapToSpeak() + self.delegate?.tapToSpeakButtonPressed() + } + + @objc func tapToSpeakPressed() { + tapToSpeakButton.isSelected = !tapToSpeakButton.isSelected + updateButtonTapToSpeak() + self.delegate?.tapToSpeakButtonPressed() + } +} diff --git a/Nynja/Resources/en.lproj/Localizable.strings b/Nynja/Resources/en.lproj/Localizable.strings index df12295b0a582cb3000872ed85087eba2b39ec79..57cd1e724dc4179b8be8b5d6264b12068fabc99e 100644 --- a/Nynja/Resources/en.lproj/Localizable.strings +++ b/Nynja/Resources/en.lproj/Localizable.strings @@ -883,3 +883,16 @@ "interpretation_language_not_selected" = "Please, choose the language you want to interpret from."; "interpretation_languages_are_equal" = "Please, choose different languages."; + +// MARK: Hold To Speak +"hold_to_speak_title" = "Hold to Speak Mode"; +"hold_to_speak_button_leave" = "Leave"; +"hold_to_speak_button" = "Hold to\nSpeak"; +"hold_to_speak_button_done" = "Done\nSpeaking"; +"hold_to_speak_label_micr_off" = "Yоur microphone is turned off"; +"hold_to_speak_label_micr_on" = "Yоur microphone is turned on"; + + + + +