|  |  |  | // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import UIKit | 
					
						
							|  |  |  | import SessionUIKit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | open class ScreenLockViewController: UIViewController { | 
					
						
							|  |  |  |     public enum State { | 
					
						
							|  |  |  |         case none | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         /// Shown while app is inactive or background, if enabled. | 
					
						
							|  |  |  |         case protection | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         /// Shown while app is active, if enabled. | 
					
						
							|  |  |  |         case lock | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     public override var preferredStatusBarStyle: UIStatusBarStyle { | 
					
						
							|  |  |  |         return ThemeManager.currentTheme.statusBarStyle | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     public override var canBecomeFirstResponder: Bool { true } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     public var onUnlockPressed: (() -> ())? | 
					
						
							|  |  |  |     private var screenBlockingSignature: String? | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // MARK: - UI | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     private let logoView: UIImageView = { | 
					
						
							|  |  |  |         let result: UIImageView = UIImageView(image: #imageLiteral(resourceName: "SessionGreen64")) | 
					
						
							|  |  |  |         result.contentMode = .scaleAspectFit | 
					
						
							|  |  |  |         result.isHidden = true | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  |     }() | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     public lazy var unlockButton: SessionButton = { | 
					
						
							|  |  |  |         let result: SessionButton = SessionButton(style: .bordered, size: .medium) | 
					
						
							|  |  |  |         result.translatesAutoresizingMaskIntoConstraints = false | 
					
						
							|  |  |  |         result.setTitle("lockAppUnlock".localized(), for: .normal) | 
					
						
							|  |  |  |         result.addTarget(self, action: #selector(showUnlockUI), for: .touchUpInside) | 
					
						
							|  |  |  |         result.isHidden = true | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Need to match the launch screen so force the styling to be the primary green | 
					
						
							|  |  |  |         result.setThemeTitleColorForced(.primary(.green), for: .normal) | 
					
						
							|  |  |  |         result.setThemeBackgroundColorForced(.primary(.green), for: .highlighted) | 
					
						
							|  |  |  |         result.themeBorderColorForced = .primary(.green) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return result | 
					
						
							|  |  |  |     }() | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // MARK: - Lifecycle | 
					
						
							|  |  |  |                                    | 
					
						
							|  |  |  |     public init(onUnlockPressed: (() -> ())? = nil) { | 
					
						
							|  |  |  |         self.onUnlockPressed = onUnlockPressed | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         super.init(nibName: nil, bundle: nil) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |                                    | 
					
						
							|  |  |  |     required public init?(coder: NSCoder) { | 
					
						
							|  |  |  |         fatalError("init(coder:) has not been implemented") | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |                                    | 
					
						
							|  |  |  |     open override func loadView() { | 
					
						
							|  |  |  |         super.loadView() | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         view.themeBackgroundColorForced = .theme(.classicDark, color: .black)  // Need to match the Launch screen | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let edgesView: UIView = UIView() | 
					
						
							|  |  |  |         edgesView.layoutMargins = .zero | 
					
						
							|  |  |  |         self.view.addSubview(edgesView) | 
					
						
							|  |  |  |         edgesView.pin(to: view) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         edgesView.addSubview(logoView) | 
					
						
							|  |  |  |         logoView.center(in: edgesView) | 
					
						
							|  |  |  |         logoView.set(.width, to: 64) | 
					
						
							|  |  |  |         logoView.set(.height, to: 64) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         edgesView.addSubview(unlockButton) | 
					
						
							|  |  |  |         unlockButton.pin(.top, to: .bottom, of: logoView, withInset: Values.mediumSpacing) | 
					
						
							|  |  |  |         unlockButton.center(.horizontal, in: view) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         updateUI(state: .protection, animated: false) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     /// The "screen blocking" window has three possible states: | 
					
						
							|  |  |  |     /// | 
					
						
							|  |  |  |     /// * "Just a logo".  Used when app is launching and in app switcher.  Must match the "Launch Screen" storyboard pixel-for-pixel. | 
					
						
							|  |  |  |     /// * "Screen Lock, local auth UI presented". Must match the "Launch Screen" storyboard pixel-for-pixel. | 
					
						
							|  |  |  |     /// * "Screen Lock, local auth UI not presented". Show "unlock" button. | 
					
						
							|  |  |  |     public func updateUI(state: State, animated: Bool) { | 
					
						
							|  |  |  |         guard isViewLoaded else { return } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let shouldShowBlockWindow: Bool = (state != .none) | 
					
						
							|  |  |  |         let shouldHaveScreenLock: Bool = (state == .lock) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.logoView.isHidden = !shouldShowBlockWindow | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let signature: String = String(format: "%d", shouldHaveScreenLock) | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         // Skip redundant work to avoid interfering with ongoing animations | 
					
						
							|  |  |  |         guard signature != self.screenBlockingSignature else { return } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         self.unlockButton.isHidden = !shouldHaveScreenLock | 
					
						
							|  |  |  |         self.screenBlockingSignature = signature | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         guard animated else { | 
					
						
							|  |  |  |             self.view.setNeedsLayout() | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         UIView.animate(withDuration: 0.3) { [weak self] in | 
					
						
							|  |  |  |             self?.view.layoutIfNeeded() | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     @objc private func showUnlockUI() { | 
					
						
							|  |  |  |         self.onUnlockPressed?() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |