|  |  |  | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import UIKit | 
					
						
							|  |  |  | import SessionUIKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | final class OptionView: UIView { | 
					
						
							|  |  |  |     private let title: String | 
					
						
							|  |  |  |     private let explanation: String | 
					
						
							|  |  |  |     private let delegate: OptionViewDelegate | 
					
						
							|  |  |  |     private let isRecommended: Bool | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     var isSelected = false { didSet { handleIsSelectedChanged() } } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private static let cornerRadius: CGFloat = 8 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     init(title: String, explanation: String, delegate: OptionViewDelegate, isRecommended: Bool = false) { | 
					
						
							|  |  |  |         self.title = title | 
					
						
							|  |  |  |         self.explanation = explanation | 
					
						
							|  |  |  |         self.delegate = delegate | 
					
						
							|  |  |  |         self.isRecommended = isRecommended | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         super.init(frame: CGRect.zero) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         setUpViewHierarchy() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     override init(frame: CGRect) { | 
					
						
							|  |  |  |         preconditionFailure("Use init(string:explanation:) instead.") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     required init?(coder: NSCoder) { | 
					
						
							|  |  |  |         preconditionFailure("Use init(string:explanation:) instead.") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private func setUpViewHierarchy() { | 
					
						
							|  |  |  |         themeBackgroundColor = .backgroundSecondary | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Round corners | 
					
						
							|  |  |  |         layer.cornerRadius = OptionView.cornerRadius | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up border | 
					
						
							|  |  |  |         themeBorderColor = .borderSeparator | 
					
						
							|  |  |  |         layer.borderWidth = 1 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up shadow | 
					
						
							|  |  |  |         themeShadowColor = .black | 
					
						
							|  |  |  |         layer.shadowOffset = CGSize(width: 0, height: 0.8) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         ThemeManager.onThemeChange(observer: self) { [weak self] theme, _ in | 
					
						
							|  |  |  |             switch theme.interfaceStyle { | 
					
						
							|  |  |  |                 case .light: | 
					
						
							|  |  |  |                     self?.layer.shadowOpacity = 0.16 | 
					
						
							|  |  |  |                     self?.layer.shadowRadius = 4 | 
					
						
							|  |  |  |                      | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     self?.layer.shadowOpacity = 1 | 
					
						
							|  |  |  |                     self?.layer.shadowRadius = 6 | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up title label | 
					
						
							|  |  |  |         let titleLabel: UILabel = UILabel() | 
					
						
							|  |  |  |         titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) | 
					
						
							|  |  |  |         titleLabel.text = title | 
					
						
							|  |  |  |         titleLabel.themeTextColor = .textPrimary | 
					
						
							|  |  |  |         titleLabel.lineBreakMode = .byWordWrapping | 
					
						
							|  |  |  |         titleLabel.numberOfLines = 0 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up explanation label | 
					
						
							|  |  |  |         let explanationLabel: UILabel = UILabel() | 
					
						
							|  |  |  |         explanationLabel.font = .systemFont(ofSize: Values.verySmallFontSize) | 
					
						
							|  |  |  |         explanationLabel.text = explanation | 
					
						
							|  |  |  |         explanationLabel.themeTextColor = .textPrimary | 
					
						
							|  |  |  |         explanationLabel.lineBreakMode = .byWordWrapping | 
					
						
							|  |  |  |         explanationLabel.numberOfLines = 0 | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up stack view | 
					
						
							|  |  |  |         let stackView = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel ]) | 
					
						
							|  |  |  |         stackView.axis = .vertical | 
					
						
							|  |  |  |         stackView.spacing = 4 | 
					
						
							|  |  |  |         stackView.alignment = .fill | 
					
						
							|  |  |  |         addSubview(stackView) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         stackView.pin(.leading, to: .leading, of: self, withInset: 12) | 
					
						
							|  |  |  |         stackView.pin(.top, to: .top, of: self, withInset: 12) | 
					
						
							|  |  |  |         self.pin(.trailing, to: .trailing, of: stackView, withInset: 12) | 
					
						
							|  |  |  |         self.pin(.bottom, to: .bottom, of: stackView, withInset: 12) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up recommended label if needed | 
					
						
							|  |  |  |         if isRecommended { | 
					
						
							|  |  |  |             let recommendedLabel: UILabel = UILabel() | 
					
						
							|  |  |  |             recommendedLabel.font = .boldSystemFont(ofSize: Values.smallFontSize) | 
					
						
							|  |  |  |             recommendedLabel.text = "vc_pn_mode_recommended_option_tag".localized() | 
					
						
							|  |  |  |             recommendedLabel.themeTextColor = .primary | 
					
						
							|  |  |  |             stackView.addArrangedSubview(recommendedLabel) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Set up tap gesture recognizer | 
					
						
							|  |  |  |         let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) | 
					
						
							|  |  |  |         addGestureRecognizer(tapGestureRecognizer) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @objc private func handleTap() { | 
					
						
							|  |  |  |         isSelected = !isSelected | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private func handleIsSelectedChanged() { | 
					
						
							|  |  |  |         UIView.animate(withDuration: 0.3) { [weak self] in | 
					
						
							|  |  |  |             self?.themeBorderColor = (self?.isSelected == true ? .primary : .borderSeparator) | 
					
						
							|  |  |  |             self?.themeShadowColor = (self?.isSelected == true ? .primary : .black) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Notify delegate | 
					
						
							|  |  |  |         if isSelected { delegate.optionViewDidActivate(self) } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // MARK: - Option View Delegate | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protocol OptionViewDelegate { | 
					
						
							|  |  |  |     func optionViewDidActivate(_ optionView: OptionView) | 
					
						
							|  |  |  | } |