session-ios/SessionShareExtension/SAEScreenLockViewController.swift
2022-01-11 12:38:19 +11:00

206 lines
6.4 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import UIKit
import PromiseKit
import SignalCoreKit
import SignalUtilitiesKit
import SessionUIKit
import SessionUtilitiesKit
final class SAEScreenLockViewController: ScreenLockViewController, ScreenLockViewDelegate {
private var hasShownAuthUIOnce: Bool = false
private var isShowingAuthUI: Bool = false
private weak var shareViewDelegate: ShareViewDelegate?
// MARK: - Initialization
init(shareViewDelegate: ShareViewDelegate) {
super.init(nibName: nil, bundle: nil)
self.shareViewDelegate = shareViewDelegate
self.delegate = self
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
OWSLogger.verbose("Dealloc: \(type(of: self))")
}
// MARK: - UI
private lazy var gradientBackground: CAGradientLayer = {
let layer: CAGradientLayer = CAGradientLayer()
let gradientStartColor: UIColor = (LKAppModeUtilities.isLightMode ?
UIColor(rgbHex: 0xFCFCFC) :
UIColor(rgbHex: 0x171717)
)
let gradientEndColor: UIColor = (LKAppModeUtilities.isLightMode ?
UIColor(rgbHex: 0xFFFFFF) :
UIColor(rgbHex: 0x121212)
)
layer.colors = [gradientStartColor.cgColor, gradientEndColor.cgColor]
return layer
}()
private lazy var titleLabel: UILabel = {
let titleLabel: UILabel = UILabel()
titleLabel.font = UIFont.boldSystemFont(ofSize: Values.veryLargeFontSize)
titleLabel.text = "vc_share_title".localized()
titleLabel.textColor = Colors.text
return titleLabel
}()
private lazy var closeButton: UIBarButtonItem = {
let closeButton: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "X"), style: .plain, target: self, action: #selector(dismissPressed))
closeButton.tintColor = Colors.text
return closeButton
}()
// MARK: - Lifecycle
override func loadView() {
super.loadView()
UIView.appearance().tintColor = Colors.text
self.view.backgroundColor = UIColor.clear
self.view.layer.insertSublayer(gradientBackground, at: 0)
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.tintColor = Colors.navigationBarBackground
self.navigationItem.titleView = titleLabel
self.navigationItem.leftBarButtonItem = closeButton
setupLayout()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.ensureUI()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.ensureUI()
// Auto-show the auth UI f
if !hasShownAuthUIOnce {
hasShownAuthUIOnce = true
self.tryToPresentAuthUIToUnlockScreenLock()
}
}
// MARK: - Layout
private func setupLayout() {
gradientBackground.frame = UIScreen.main.bounds
}
// MARK: - Functions
private func tryToPresentAuthUIToUnlockScreenLock() {
AssertIsOnMainThread()
// If we're already showing the auth UI; abort.
if self.isShowingAuthUI { return }
OWSLogger.info("try to unlock screen lock")
isShowingAuthUI = true
OWSScreenLock.shared.tryToUnlockScreenLock(
success: { [weak self] in
AssertIsOnMainThread()
OWSLogger.info("unlock screen lock succeeded.")
self?.isShowingAuthUI = false
self?.shareViewDelegate?.shareViewWasUnlocked()
},
failure: { [weak self] error in
AssertIsOnMainThread()
OWSLogger.info("unlock screen lock failed.")
self?.isShowingAuthUI = false
self?.ensureUI()
self?.showScreenLockFailureAlert(message: error.localizedDescription)
},
unexpectedFailure: { [weak self] error in
AssertIsOnMainThread()
OWSLogger.info("unlock screen lock unexpectedly failed.")
self?.isShowingAuthUI = false
// Local Authentication isn't working properly.
// This isn't covered by the docs or the forums but in practice
// it appears to be effective to retry again after waiting a bit.
DispatchQueue.main.async {
self?.ensureUI()
}
},
cancel: { [weak self] in
AssertIsOnMainThread()
OWSLogger.info("unlock screen lock cancelled.")
self?.isShowingAuthUI = false
self?.ensureUI()
}
)
self.ensureUI()
}
private func ensureUI() {
self.updateUI(with: .screenLock, isLogoAtTop: false, animated: false)
}
private func showScreenLockFailureAlert(message: String) {
AssertIsOnMainThread()
OWSAlerts.showAlert(
// Title for alert indicating that screen lock could not be unlocked.
title: "SCREEN_LOCK_UNLOCK_FAILED".localized(),
message: message,
buttonTitle: nil,
buttonAction: { [weak self] action in
// After the alert, update the UI
self?.ensureUI()
},
fromViewController: self
)
}
// MARK: - Transitions
@objc private func dismissPressed() {
OWSLogger.debug("unlock screen lock cancelled.")
self.cancelShareExperience()
}
private func cancelShareExperience() {
self.shareViewDelegate?.shareViewWasCancelled()
}
// MARK: - ScreenLockViewDelegate
func unlockButtonWasTapped() {
AssertIsOnMainThread()
OWSLogger.info("unlockButtonWasTapped")
self.tryToPresentAuthUIToUnlockScreenLock()
}
}