Files

255 lines
10 KiB
Swift

//
// LaunchScreenIPAD.swift
// PrivadoVPN
//
// Created by Lizaveta Malinouskaya on 6/22/21.
// Copyright © 2021 Privado LLC. All rights reserved.
//
import Foundation
import UIKit
final class LaunchScreenControllerIPAD: UIViewController, UITextViewDelegate {
private enum Constants {
enum Color {
static let backGradientTop = Colors.SystemBackgrounds.GradientActive.top.color
static let backGradientBottom = Colors.SystemBackgrounds.GradientActive.bottom.color
static let title = Colors.basicText.color
static let createButtonBackground = Colors.Button.background.color
static let createButtonText = Colors.Button.text.color
static let loginButtonText = Colors.Button.text.color
static let errorText = Colors.TextField.error.color
static let scrollBarColor = Colors.Base.primaryLightGrey.color
}
enum Geometry {
enum Shared {
static let buttonTop: CGFloat = 50
static let labelBottom: CGFloat = 50
static let labelHeight: CGFloat = 30
static let labelWidth: CGFloat = 340
static let buttonHeight: CGFloat = 50
static let buttonWidth: CGFloat = 344
static let scrollViewHeight: CGFloat = 537
}
enum Portrait {
static let scrollViewInset: CGFloat = (UIScreen.main.bounds.width - 586) / 2
}
enum Landscape {
static let scrollViewInset: CGFloat = (UIScreen.main.bounds.width - 670) / 2
}
}
enum LocalizedString {
static let button = "launch.button"
static let content = "launch.content"
static let label = "launch.top"
}
enum Font {
static let title = UIFont.primary(size: 27, weight: .semibold)
static let button = UIFont.primary(size: 16, weight: .bold)
static let content = UIFont.primary(size: 19, weight: .semibold)
}
}
private let output: LaunchScreenControllerOutput
private var compactConstraints = [NSLayoutConstraint]()
private var regularConstraints = [NSLayoutConstraint]()
private var sharedConstraints = [NSLayoutConstraint]()
private let isLandscapeModeEmitter = Emitter<Bool>()
private var textView: UITextView?
// MARK: - Init
init(output: LaunchScreenControllerOutput) {
self.output = output
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: - Lyfecycle
override func loadView() {
let view = UIView(frame: .zero)
view.autoresizesSubviews = true
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .black
self.view = view
}
override func viewDidLoad() {
super.viewDidLoad()
self.configureUI()
self.isLandscapeModeEmitter.addReaction { [weak self] isLandscape -> ShouldContinueReceiveNotifications in
self?.activateLayoutFor(landscape: isLandscape)
return self.isExist
}
self.output.viewIsReady()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if let superview = self.view.superview {
NSLayoutConstraint.activate([
self.view.topAnchor.constraint(equalTo: superview.topAnchor),
self.view.leadingAnchor.constraint(equalTo: superview.leadingAnchor),
self.view.trailingAnchor.constraint(equalTo: superview.trailingAnchor),
self.view.bottomAnchor.constraint(equalTo: superview.bottomAnchor)
])
}
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent // .default
}
// MARK: - UI
private func configureUI() {
self.view.translatesAutoresizingMaskIntoConstraints = false
let gradientView = self.initializeBackgroundGradient(using: self.view)
let circleLeft = self.initializeFadedCircles(using: self.view)
let circleRight = self.initializeFadedCircles(using: self.view)
let logoTitle = self.initializeTitleLabel(using: self.view)
let agreeButton = self.initializeAgreeButton(using: self.view)
let scrollView = self.initializeScrollView(using: self)
// MARK: - Shared constraints
self.sharedConstraints = [
// Circles
circleLeft.centerXAnchor.constraint(equalTo: self.view.leadingAnchor),
circleRight.centerXAnchor.constraint(equalTo: self.view.trailingAnchor),
circleRight.centerYAnchor.constraint(equalTo: self.view.bottomAnchor),
// Gradient view
gradientView.topAnchor.constraint(equalTo: self.view.topAnchor),
gradientView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
gradientView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
gradientView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
// Logo title
logoTitle.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
logoTitle.widthAnchor.constraint(equalToConstant: Constants.Geometry.Shared.labelWidth),
logoTitle.heightAnchor.constraint(equalToConstant: Constants.Geometry.Shared.labelHeight),
logoTitle.bottomAnchor.constraint(equalTo: scrollView.topAnchor, constant: -Constants.Geometry.Shared.labelBottom),
// Scroll view
scrollView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
scrollView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
scrollView.heightAnchor.constraint(equalToConstant: Constants.Geometry.Shared.scrollViewHeight),
// Create button
agreeButton.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: Constants.Geometry.Shared.buttonTop),
agreeButton.heightAnchor.constraint(equalToConstant: Constants.Geometry.Shared.buttonHeight),
agreeButton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
agreeButton.widthAnchor.constraint(equalToConstant: Constants.Geometry.Shared.buttonWidth)
]
// MARK: - Portrait constraints
self.compactConstraints = [
// Scroll view
scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: Constants.Geometry.Portrait.scrollViewInset),
scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -Constants.Geometry.Portrait.scrollViewInset)
]
// MARK: - Landscape constraints
self.regularConstraints = [
// Scroll view
scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: Constants.Geometry.Landscape.scrollViewInset),
scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -Constants.Geometry.Landscape.scrollViewInset)
]
let landscape = DeviceInfoProvider.isLandscapeOrienation && self.traitCollection.horizontalSizeClass == .regular
self.activateLayoutFor(landscape: landscape)
}
private func activateLayoutFor(landscape: Bool) {
if landscape {
NSLayoutConstraint.deactivate(self.compactConstraints)
NSLayoutConstraint.activate(self.regularConstraints)
} else {
NSLayoutConstraint.deactivate(self.regularConstraints)
NSLayoutConstraint.activate(self.compactConstraints)
}
NSLayoutConstraint.activate(self.sharedConstraints)
}
private func initializeBackgroundGradient(using container: UIView) -> UIView {
let gradientView = GradientView()
gradientView.translatesAutoresizingMaskIntoConstraints = false
gradientView.horizontalMode = false
gradientView.stops = [
.init(color: Constants.Color.backGradientTop, location: 0),
.init(color: Constants.Color.backGradientBottom, location: 1)
]
container.addSubview(gradientView)
return gradientView
}
private func initializeTitleLabel(using container: UIView) -> UILabel {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = NSLocalizedString(Constants.LocalizedString.label, comment: "Fast and Secure VPN You Can Trust")
label.font = Constants.Font.title
label.textColor = Constants.Color.title
label.numberOfLines = 0
label.textAlignment = .center
container.addSubview(label)
return label
}
private func initializeAgreeButton(using container: UIView) -> UIButton {
let button = UIButton(frame: .zero)
button.translatesAutoresizingMaskIntoConstraints = false
button.layer.cornerRadius = Constants.Geometry.Shared.buttonHeight / 2
button.clipsToBounds = true
button.backgroundColor = Constants.Color.createButtonBackground
button.setTitleColor(Constants.Color.createButtonText, for: .normal)
button.titleLabel?.font = Constants.Font.button
button.setTitle(NSLocalizedString(Constants.LocalizedString.button, comment: "Agree & Continue"), for: .normal)
button.addTarget(self, action: #selector(self.buttonClick), for: .touchUpInside)
container.addSubview(button)
return button
}
private func initializeFadedCircles(using container: UIView) -> UIView {
let circles = BackgroundCircles()
circles.translatesAutoresizingMaskIntoConstraints = false
container.addSubview(circles)
return circles
}
private func initializeScrollView(using container: (UIViewController & UITextViewDelegate)) -> UITextView {
let view = LaunchScreenScrollView()
view.delegate = container
container.view.addSubview(view)
return view
}
@objc
func buttonClick() {
self.output.agreeClick()
}
// MARK: Scroll view delegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard let verticalIndicator = (scrollView.subviews[safe: (scrollView.subviews.count - 1)]?.subviews[safe: 0]) else { return }
verticalIndicator.backgroundColor = Constants.Color.scrollBarColor
}
}