// // MessageView.swift // PrivadoVPN // // Created by Zhandos Bolatbekov on 25.01.2021. // Copyright © 2021 Privado LLC. All rights reserved. // import Foundation import UIKit protocol MessageViewInput: AnyObject { func showMessage(text: String) func setVisibility(hidden: Bool) } protocol MessageViewOutput: AnyObject { func didTap() func changeVisibility(isHidden: Bool) func didTapViewButton() func didTapClose() } final class MessageView: UIView, MessageViewInput { private enum Constants { enum Color { static let background = UIColor.clear static let messageContainerBackground = UIColor(rgb: 0x363f83) static let messageText = UIColor(rgb: 0x28d799) static let button = UIColor(rgb: 0x030f48) static let buttonSeparator = UIColor(rgb: 0x363f83) } enum Geometry { static let height: CGFloat = 53 static let messageIndent: CGFloat = 16 static let buttonsWidth: CGFloat = 158 static let buttonsSeparatorWidth: CGFloat = 1 static let buttonsIndentY: CGFloat = 6 static let cornerRadius: CGFloat = 5 } enum LocalizedString { static let viewButton = "messageView.button.view" static let closeButton = "messageView.button.close" } static let messageFont = UIFont(name: "SFProText-Regular", size: 16.7) static let swipeAnimationDuration: Double = 0.2 } private let output: MessageViewOutput private var messageLabel: UILabel? private var messageContainerRightConstraint: NSLayoutConstraint? // MARK: - Init init(output: MessageViewOutput) { self.output = output super.init(frame: .zero) self.configureUI() } required init?(coder: NSCoder) { nil } // MARK: - View private func configureUI() { self.translatesAutoresizingMaskIntoConstraints = false self.backgroundColor = Constants.Color.background self.layer.cornerRadius = Constants.Geometry.cornerRadius self.layer.maskedCorners = [.layerMinXMaxYCorner, .layerMaxXMaxYCorner] self.clipsToBounds = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.onTapGesture)) self.addGestureRecognizer(tapGesture) let buttonsView = self.initializeButtons() NSLayoutConstraint.activate([ buttonsView.widthAnchor.constraint(equalToConstant: Constants.Geometry.buttonsWidth), buttonsView.topAnchor.constraint(equalTo: self.topAnchor), buttonsView.bottomAnchor.constraint(equalTo: self.bottomAnchor), buttonsView.rightAnchor.constraint(equalTo: self.rightAnchor) ]) let messageContainer = self.initializeMessageContainer() self.addSubview(messageContainer) self.messageContainerRightConstraint = messageContainer.rightAnchor.constraint(equalTo: self.rightAnchor) NSLayoutConstraint.activate([ messageContainer.heightAnchor.constraint(equalToConstant: Constants.Geometry.height), messageContainer.topAnchor.constraint(equalTo: self.topAnchor), messageContainer.bottomAnchor.constraint(equalTo: self.bottomAnchor), messageContainer.widthAnchor.constraint(equalTo: self.widthAnchor), self.messageContainerRightConstraint! ]) let messageLabel = self.createMessageLabel() messageContainer.addSubview(messageLabel) NSLayoutConstraint.activate([ messageLabel.leftAnchor.constraint(equalTo: messageContainer.leftAnchor, constant: Constants.Geometry.messageIndent), messageLabel.rightAnchor.constraint(equalTo: messageContainer.rightAnchor, constant: -Constants.Geometry.messageIndent), messageLabel.centerYAnchor.constraint(equalTo: messageContainer.centerYAnchor) ]) } // MARK: - MessageViewInput func showMessage(text: String) { self.messageLabel?.attributedText = NSAttributedString( string: text, attributes: [.underlineStyle: NSUnderlineStyle.single.rawValue, .kern: -1.0] ) self.output.changeVisibility(isHidden: false) } func setVisibility(hidden: Bool) { } // MARK: - Private private func initializeMessageContainer() -> UIView { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = Constants.Color.messageContainerBackground let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(self.leftSwipeAction)) leftSwipe.direction = .right // view.addGestureRecognizer(leftSwipe) let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(self.rightSwipeAction)) rightSwipe.direction = .left // view.addGestureRecognizer(rightSwipe) return view } private func createMessageLabel() -> UILabel { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false label.font = Constants.messageFont label.lineBreakMode = .byTruncatingTail label.textColor = Constants.Color.messageText label.textAlignment = .center self.messageLabel = label return label } private func initializeButtons() -> UIView { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false let separator: UIView = { let view = UIView() view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = Constants.Color.buttonSeparator return view }() view.addSubview(separator) NSLayoutConstraint.activate([ separator.centerXAnchor.constraint(equalTo: view.centerXAnchor), separator.widthAnchor.constraint(equalToConstant: Constants.Geometry.buttonsSeparatorWidth), separator.topAnchor.constraint(equalTo: view.topAnchor, constant: Constants.Geometry.buttonsIndentY), separator.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -Constants.Geometry.buttonsIndentY) ]) let viewButtonTitle = NSLocalizedString(Constants.LocalizedString.viewButton, comment: "View") let viewButton = self.createButton(title: viewButtonTitle) viewButton.addTarget(self, action: #selector(self.didTapViewButton), for: .touchUpInside) view.addSubview(viewButton) NSLayoutConstraint.activate([ viewButton.topAnchor.constraint(equalTo: view.topAnchor), viewButton.leadingAnchor.constraint(equalTo: view.leadingAnchor), viewButton.trailingAnchor.constraint(equalTo: separator.leadingAnchor), viewButton.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) let closeButtonTitle = NSLocalizedString(Constants.LocalizedString.closeButton, comment: "Close") let closeButton = self.createButton(title: closeButtonTitle) closeButton.addTarget(self, action: #selector(self.didTapCloseButton), for: .touchUpInside) view.addSubview(closeButton) NSLayoutConstraint.activate([ closeButton.topAnchor.constraint(equalTo: view.topAnchor), closeButton.leadingAnchor.constraint(equalTo: separator.trailingAnchor), closeButton.trailingAnchor.constraint(equalTo: view.trailingAnchor), closeButton.bottomAnchor.constraint(equalTo: view.bottomAnchor) ]) self.addSubview(view) return view } private func createButton(title: String) -> UIButton { let button = UIButton() button.translatesAutoresizingMaskIntoConstraints = false button.setTitle(title, for: .normal) button.backgroundColor = Constants.Color.button return button } @objc private func onTapGesture() { self.output.didTap() } @objc private func leftSwipeAction() { UIView.animate(withDuration: Constants.swipeAnimationDuration) { [weak self] in self?.messageContainerRightConstraint?.constant = 0 self?.layoutIfNeeded() } } @objc private func rightSwipeAction() { UIView.animate(withDuration: Constants.swipeAnimationDuration) { [weak self] in self?.messageContainerRightConstraint?.constant = -Constants.Geometry.buttonsWidth self?.layoutIfNeeded() } } @objc private func didTapViewButton() { self.output.didTapViewButton() } @objc private func didTapCloseButton() { self.output.didTapClose() } }