diff --git a/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.swift b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.swift new file mode 100644 index 000000000..73961e2eb --- /dev/null +++ b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.swift @@ -0,0 +1,157 @@ +/* + Copyright 2020 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import UIKit +import Reusable + +final class SecureKeyBackupSetupIntroCell: UIView, NibOwnerLoadable, Themable { + + // MARK: - Constants + + private enum ImageAlpha { + static let highlighted: CGFloat = 0.3 + } + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var backgroundView: UIView! + @IBOutlet private weak var imageView: UIImageView! + @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet private weak var informationLabel: UILabel! + @IBOutlet private weak var accessoryImageView: UIImageView! + @IBOutlet private weak var separatorView: UIView! + + // MARK: Private + + private var theme: Theme? + + private var isHighlighted: Bool = false { + didSet { + self.updateView() + } + } + + // MARK: Public + + var action: (() -> Void)? + + // MARK: Setup + + private func commonInit() { + self.setupGestureRecognizer() + + let accessoryTemplateImage = Asset.Images.disclosureIcon.image.withRenderingMode(.alwaysTemplate) + self.accessoryImageView.image = accessoryTemplateImage + self.accessoryImageView.highlightedImage = accessoryTemplateImage.vc_withAlpha(ImageAlpha.highlighted) + } + + convenience init() { + self.init(frame: CGRect.zero) + self.commonInit() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.loadNibContent() + self.commonInit() + } + + override init(frame: CGRect) { + super.init(frame: frame) + self.loadNibContent() + self.commonInit() + } + + // MARK: - Public + + func update(theme: Theme) { + self.theme = theme + + self.backgroundView.backgroundColor = theme.backgroundColor + self.imageView.tintColor = theme.textPrimaryColor + self.titleLabel.textColor = theme.tintColor + self.informationLabel.textColor = theme.textSecondaryColor + self.accessoryImageView.tintColor = theme.textSecondaryColor + self.separatorView.backgroundColor = theme.lineBreakColor + + self.updateView() + } + + func fill(title: String, information: String, image: UIImage) { + let templateImage = image.withRenderingMode(.alwaysTemplate) + + self.imageView.image = templateImage + self.imageView.highlightedImage = templateImage.vc_withAlpha(ImageAlpha.highlighted) + + self.titleLabel.text = title + self.informationLabel.text = information + + self.setupAccessibility(title: title, isEnabled: true) + self.updateView() + } + + // MARK: - Private + + private func setupAccessibility(title: String, isEnabled: Bool) { + self.isAccessibilityElement = true + self.accessibilityLabel = title + self.accessibilityTraits = .button + if !isEnabled { + self.accessibilityTraits.insert(.notEnabled) + } + } + + private func setupGestureRecognizer() { + let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(buttonAction(_:))) + gestureRecognizer.minimumPressDuration = 0 + self.addGestureRecognizer(gestureRecognizer) + } + + private func updateView() { + + if let theme = self.theme { + self.backgroundView.backgroundColor = self.isHighlighted ? theme.overlayBackgroundColor : theme.backgroundColor + } + + self.imageView.isHighlighted = self.isHighlighted + self.accessoryImageView.isHighlighted = self.isHighlighted + } + + // MARK: - Actions + + @objc private func buttonAction(_ sender: UILongPressGestureRecognizer) { + + let isBackgroundViewTouched = sender.vc_isTouchingInside() + + switch sender.state { + case .began, .changed: + self.isHighlighted = isBackgroundViewTouched + case .ended: + self.isHighlighted = false + + if isBackgroundViewTouched { + self.action?() + } + case .cancelled: + self.isHighlighted = false + default: + break + } + } + +} diff --git a/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.xib b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.xib new file mode 100644 index 000000000..3b29fac64 --- /dev/null +++ b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroCell.xib @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.storyboard b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.storyboard new file mode 100644 index 000000000..0f6dd3102 --- /dev/null +++ b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.storyboard @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.swift b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.swift new file mode 100644 index 000000000..9213b3024 --- /dev/null +++ b/Riot/Modules/KeyBackup/SecureSetup/Intro/SecureKeyBackupSetupIntroViewController.swift @@ -0,0 +1,133 @@ +/* + Copyright 2020 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import UIKit + +protocol SecureKeyBackupSetupIntroViewControllerDelegate: class { + func secureKeyBackupSetupIntroViewControllerDidTapUseKey(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) + func secureKeyBackupSetupIntroViewControllerDidTapUsePassphrase(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) + func secureKeyBackupSetupIntroViewControllerDidCancel(_ secureKeyBackupSetupIntroViewController: SecureKeyBackupSetupIntroViewController) +} + +@objcMembers +final class SecureKeyBackupSetupIntroViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var topSeparatorView: UIView! + @IBOutlet private weak var secureKeyCell: SecureKeyBackupSetupIntroCell! + @IBOutlet private weak var securePassphraseCell: SecureKeyBackupSetupIntroCell! + + // MARK: Private + + private var theme: Theme! + + // MARK: Public + + weak var delegate: SecureKeyBackupSetupIntroViewControllerDelegate? + + // MARK: - Setup + + class func instantiate() -> SecureKeyBackupSetupIntroViewController { + let viewController = StoryboardScene.SecureKeyBackupSetupIntroViewController.initialScene.instantiate() + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.vc_removeBackTitle() + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + guard let self = self else { + return + } + self.delegate?.secureKeyBackupSetupIntroViewControllerDidCancel(self) + } + self.navigationItem.rightBarButtonItem = cancelBarButtonItem + + self.title = VectorL10n.secureKeyBackupSetupIntroTitle + + self.informationLabel.text = VectorL10n.secureKeyBackupSetupIntroInfo + + self.secureKeyCell.fill(title: VectorL10n.secureKeyBackupSetupIntroUseSecurityKeyTitle, + information: VectorL10n.secureKeyBackupSetupIntroUseSecurityKeyInfo, + image: Asset.Images.secretsSetupKey.image) + + self.secureKeyCell.action = { [weak self] in + guard let self = self else { + return + } + self.delegate?.secureKeyBackupSetupIntroViewControllerDidTapUseKey(self) + } + + self.securePassphraseCell.fill(title: VectorL10n.secureKeyBackupSetupIntroUseSecurityPassphraseTitle, + information: VectorL10n.secureKeyBackupSetupIntroUseSecurityPassphraseInfo, + image: Asset.Images.secretsSetupPassphrase.image) + + self.securePassphraseCell.action = { [weak self] in + guard let self = self else { + return + } + self.delegate?.secureKeyBackupSetupIntroViewControllerDidTapUsePassphrase(self) + } + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.informationLabel.textColor = theme.textPrimaryColor + + self.topSeparatorView.backgroundColor = theme.lineBreakColor + self.secureKeyCell.update(theme: theme) + self.securePassphraseCell.update(theme: theme) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } +}