// // CredentialsControllerIPAD.swift // PrivadoVPN // // Created by Lizaveta Malinouskaya on 21.10.21. // Copyright © 2021 Privado LLC. All rights reserved. // import UIKit class CredentialsControllerIPAD: BaseViewController { // MARK: - Constant enum Constant { enum Geometry { enum Shared { static let buttonSize = CGSize(width: 418, height: 60) static let labelWidth: CGFloat = 407 static let lineSpacing: CGFloat = 15 } enum Portrait { static let logoTop: CGFloat = 130 static let titleTop: CGFloat = 88 static let subtitleTop: CGFloat = 19 static let emailTop: CGFloat = 63 static let credentialsTop: CGFloat = 52 static let bottomTitleTop: CGFloat = 28 static let bottomSubtitleTop: CGFloat = 50 static let buttonTop: CGFloat = 32 } enum Landscape { static let logoTop: CGFloat = 90 static let titleTop: CGFloat = 31 static let subtitleTop: CGFloat = 19 static let emailTop: CGFloat = 34 static let credentialsTop: CGFloat = 33 static let bottomTitleTop: CGFloat = 38 static let bottomSubtitleTop: CGFloat = 27 static let buttonTop: CGFloat = 41 } } enum Font { static let title = UIFont.primary(size: 30, weight: .semibold) static let subtitle = UIFont.primary(size: 24, weight: .medium) static let email = UIFont.primary(size: 28, weight: .medium) static let bottomTitle = UIFont.primary(size: 16, weight: .semibold) static let bottomSubtitle = UIFont.primary(size: 16, weight: .regular) static let button = UIFont.primary(size: 16, weight: .bold) } enum Color { static let title = Colors.basicText.color static let subtitle = Colors.SystemCTA.lightPurple.color static let button = Colors.Button.background.color static let gradientTop = Colors.SystemBackgrounds.GradientActive.top.color static let gradientBottom = Colors.SystemBackgrounds.GradientActive.bottom.color } enum Image { static let title = UIImage(named: "logo.signup.notext") } enum LocalizedString { static let title = NSLocalizedString("credentials.header.title.ipad", comment: "Welcome to PrivadoVPN") static let subtitle = NSLocalizedString("credentials.heades.subtitle.ipad", comment: "Login to connect to the PrivadoVPN network.") static let username = NSLocalizedString("credentials.username", comment: "Username") static let password = NSLocalizedString("credentials.password", comment: "Password") static let titleFooter = NSLocalizedString("credentials.footer.title.ipad", comment: "") static let subtitleFooter = NSLocalizedString("credentials.footer.subtitle.ipad", comment: "") static let button = NSLocalizedString("credentials.button.useApp", comment: "Use the app") } } // MARK: - Property private let output: CredentialsControllerOutput // MARK: - init init(output: CredentialsControllerOutput) { self.output = output super.init() } required init?(coder: NSCoder) { nil } // MARK: - Life-cycle override func viewDidLoad() { super.viewDidLoad() self.createUI() } // MARK: - UI // swiftlint:disable function_body_length private func createUI() { let gradientView = self.initializeBackgroundGradient(using: self.view) let logoView = self.initializeLogoView(using: self.view) let titleView = self.initializeLabel(using: self.view, text: Constant.LocalizedString.title, font: Constant.Font.title, textColor: Constant.Color.title) let subtitleView = self.initializeLabel(using: self.view, text: Constant.LocalizedString.subtitle, font: Constant.Font.subtitle, textColor: Constant.Color.subtitle) let emailView = self.initializeLabel(using: self.view, text: self.output.email ?? "", font: Constant.Font.email, textColor: Constant.Color.title) let credentialsView = self.initializeCredentialsView(using: self.view) let footerTitleView = self.initializeAttributedLabel( using: self.view, text: Constant.LocalizedString.titleFooter, font: Constant.Font.bottomTitle, textColor: Constant.Color.title) let footerSubtitleView = self.initializeAttributedLabel( using: self.view, text: Constant.LocalizedString.subtitleFooter, font: Constant.Font.bottomSubtitle, textColor: Constant.Color.subtitle) let buttonView = self.initializeUseAppButton(using: self.view) self.setupBasicConstraints(for: titleView, viewAbove: logoView, distanceBetween: (Constant.Geometry.Portrait.titleTop, Constant.Geometry.Landscape.titleTop)) self.setupBasicConstraints(for: subtitleView, viewAbove: titleView, distanceBetween: (Constant.Geometry.Portrait.subtitleTop, Constant.Geometry.Landscape.subtitleTop)) self.setupBasicConstraints(for: emailView, viewAbove: subtitleView, distanceBetween: (Constant.Geometry.Portrait.emailTop, Constant.Geometry.Landscape.emailTop)) self.setupBasicConstraints(for: credentialsView, viewAbove: emailView, distanceBetween: (Constant.Geometry.Portrait.credentialsTop, Constant.Geometry.Landscape.credentialsTop)) self.setupBasicConstraints(for: footerTitleView, viewAbove: credentialsView, distanceBetween: (Constant.Geometry.Portrait.bottomSubtitleTop, Constant.Geometry.Landscape.bottomSubtitleTop)) self.setupBasicConstraints(for: footerSubtitleView, viewAbove: footerTitleView, distanceBetween: (Constant.Geometry.Portrait.bottomSubtitleTop, Constant.Geometry.Landscape.bottomSubtitleTop)) self.setupBasicConstraints(for: buttonView, viewAbove: footerSubtitleView, distanceBetween: (Constant.Geometry.Portrait.buttonTop, Constant.Geometry.Landscape.buttonTop)) self.sharedConstraints.append(contentsOf: [ buttonView.widthAnchor.constraint(equalToConstant: Constant.Geometry.Shared.buttonSize.width), buttonView.heightAnchor.constraint(equalToConstant: Constant.Geometry.Shared.buttonSize.height), gradientView.leftAnchor.constraint(equalTo: self.view.leftAnchor), gradientView.rightAnchor.constraint(equalTo: self.view.rightAnchor), gradientView.topAnchor.constraint(equalTo: self.view.topAnchor), gradientView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor), footerTitleView.widthAnchor.constraint(equalToConstant: Constant.Geometry.Shared.labelWidth), credentialsView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), credentialsView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), logoView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), footerSubtitleView.widthAnchor.constraint(equalToConstant: Constant.Geometry.Shared.labelWidth) ]) self.portraitConstraints.append(contentsOf: [ logoView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: Constant.Geometry.Portrait.logoTop) ]) self.landscapeConstraints.append(contentsOf: [ logoView.topAnchor.constraint(equalTo: self.view.topAnchor, constant: Constant.Geometry.Landscape.logoTop) ]) let landscape = DeviceInfoProvider.isLandscapeOrienation && self.traitCollection.horizontalSizeClass == .regular self.layoutEmitter.invoke(landscape) } // swiftlint:enable function_body_length private func setupBasicConstraints(for view: UIView, viewAbove: UIView, distanceBetween: (portrait: CGFloat, landscape: CGFloat)) { self.sharedConstraints.append(contentsOf: [ view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor) ]) self.portraitConstraints.append(contentsOf: [ view.topAnchor.constraint(equalTo: viewAbove.bottomAnchor, constant: distanceBetween.portrait) ]) self.landscapeConstraints.append(contentsOf: [ view.topAnchor.constraint(equalTo: viewAbove.bottomAnchor, constant: distanceBetween.landscape) ]) } private func initializeAttributedLabel(using container: UIView, text: String, font: UIFont, textColor: UIColor) -> UILabel { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = Constant.Geometry.Shared.lineSpacing let attributedString = NSAttributedString(string: text, attributes: [.paragraphStyle: paragraphStyle, .foregroundColor: textColor, .font: font]) label.attributedText = attributedString label.textAlignment = .center label.numberOfLines = 2 container.addSubview(label) return label } private func initializeLabel(using container: UIView, text: String, font: UIFont, textColor: UIColor) -> UILabel { let title = UILabel() title.translatesAutoresizingMaskIntoConstraints = false title.text = text title.font = font title.textColor = textColor title.textAlignment = .center container.addSubview(title) return title } private func initializeBackgroundGradient(using container: UIView) -> UIView { let gradientView = GradientView() gradientView.translatesAutoresizingMaskIntoConstraints = false gradientView.horizontalMode = false gradientView.stops = [ .init(color: Constant.Color.gradientTop, location: 0), .init(color: Constant.Color.gradientBottom, location: 1) ] container.addSubview(gradientView) return gradientView } private func initializeLogoView(using container: UIView) -> UIView { let view = UIImageView(image: Constant.Image.title) view.translatesAutoresizingMaskIntoConstraints = false view.contentMode = .scaleAspectFit container.addSubview(view) return view } private func initializeCredentialsView(using container: UIView) -> UIView { let view = CredentialsViewIPAD(with: self.output) container.addSubview(view) return view } private func initializeUseAppButton(using container: UIView) -> UIView { let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle(Constant.LocalizedString.button, for: .normal) button.backgroundColor = Constant.Color.button button.layer.cornerRadius = 30 button.titleLabel?.textColor = Constant.Color.title button.titleLabel?.font = Constant.Font.button button.addTarget(self, action: #selector(self.didTapUseAppButton), for: .touchUpInside) container.addSubview(button) return button } @objc func didTapUseAppButton() { self.output.didTapSkip() } }