<commit_before>//
//  NotchKitWindow.swift
//  NotchKit
//
//  Created by <NAME> on 16/09/17.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import UIKit

public final class NotchKitWindow: UIWindow {
    
    // MARK:- Types
    
    public enum CornerRadius {
        case standard
        case custom(CGFloat)
    }
    
    // MARK:- Public variables
    
    /// The corner radius for the rounded view. It can be set to a custom value,
    /// or to use the standard value which sets the corner radius appropriately
    /// for the screen size
    public var cornerRadius: CornerRadius = .standard {
        didSet { updateCornerRadii() }
    }
    
    /// A Bool indicating whether bars are shown only on the iPhone X.
    ///
    /// When this property's value is true, black bars to cover the notch and
    /// the home indicator are shown only on the iPhone X.
    ///
    /// When this property's value is false, black bars and curved corners are
    /// shown on all devices
    ///
    /// The default value of this property is `false`
    public var shouldShowBarsOnlyOniPhoneX = false {
        didSet { layoutSubviews() }
    }
    
    public override var rootViewController: UIViewController? {
        didSet {
            updateRootViewController(from: oldValue, to: rootViewController)
        }
    }
    
    // MARK:- Private variables
    
    private let safeAreaInsetsKeyPath = "safeAreaInsets"
    
    private var isiPhoneX: Bool {
        return screen.nativeBounds.size == CGSize(width: 1125, height: 2436)
    }
    
    // MARK:- View hierarchy
    
    private let safeView = UIView()
    
    private let topBarView = UIView()
    private let bottomBarView = UIView()
    private let leadingBarView = UIView()
    private let trailingBarView = UIView()
    
    private let topLeftCorner = CornerView()
    private let topRightCorner = CornerView()
    private let bottomLeftCorner = CornerView()
    private let bottomRightCorner = CornerView()
    
    private var barViews: [UIView] {
        return [topBarView, bottomBarView, leadingBarView, trailingBarView]
    }
    
    private var cornerViews: [CornerView] {
        return [topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner]
    }
    
    // MARK:- Initializers
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    public override func awakeFromNib() {
        super.awakeFromNib()
        setup()
    }
    
    private func setup() {
        safeView.isUserInteractionEnabled = false
        addSubview(safeView)
        
        barViews.forEach { bar in
            bar.backgroundColor = .black
            bar.translatesAutoresizingMaskIntoConstraints = false
            safeView.addSubview(bar)
        }
        
        NSLayoutConstraint.activate([
            topBarView.topAnchor.constraint(equalTo: topAnchor),
            topBarView.bottomAnchor.constraint(equalTo: safeView.topAnchor),
            topBarView.leadingAnchor.constraint(equalTo: leadingAnchor),
            topBarView.trailingAnchor.constraint(equalTo: trailingAnchor),
            
            bottomBarView.topAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            bottomBarView.leadingAnchor.constraint(equalTo: leadingAnchor),
            bottomBarView.trailingAnchor.constraint(equalTo: trailingAnchor),
            
            leadingBarView.topAnchor.constraint(equalTo: topAnchor),
            leadingBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            leadingBarView.leadingAnchor.constraint(equalTo: leadingAnchor),
            leadingBarView.trailingAnchor.constraint(equalTo: safeView.leadingAnchor),
            
            trailingBarView.topAnchor.constraint(equalTo: topAnchor),
            trailingBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            trailingBarView.leadingAnchor.constraint(equalTo: safeView.trailingAnchor),
            trailingBarView.trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
        
        topLeftCorner.corner = .topLeft
        topRightCorner.corner = .topRight
        bottomLeftCorner.corner = .bottomLeft
        bottomRightCorner.corner = .bottomRight
        
        cornerViews.forEach { corner in
            corner.cornerRadius = 44
            corner.translatesAutoresizingMaskIntoConstraints = false
            safeView.addSubview(corner)
        }
        
        NSLayoutConstraint.activate([
            topLeftCorner.topAnchor.constraint(equalTo: safeView.topAnchor),
            topLeftCorner.leadingAnchor.constraint(equalTo: safeView.leadingAnchor),
            
            topRightCorner.topAnchor.constraint(equalTo: safeView.topAnchor),
            topRightCorner.trailingAnchor.constraint(equalTo: safeView.trailingAnchor),
            
            bottomLeftCorner.bottomAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomLeftCorner.leadingAnchor.constraint(equalTo: safeView.leadingAnchor),
            
            bottomRightCorner.bottomAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomRightCorner.trailingAnchor.constraint(equalTo: safeView.trailingAnchor)
        ])
    }
    
    deinit {
        updateRootViewController(from: rootViewController, to: nil)
    }
    
    // MARK:- UIView methods
    
    public override func layoutSubviews() {
        super.layoutSubviews()
        bringSubview(toFront: safeView)
        updateCornerRadii()
    }
    
    // MARK:- Key value observation
    
    public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard keyPath == safeAreaInsetsKeyPath,
              let view = object as? UIView,
              view.isEqual(rootViewController?.view)
        else {
            return
        }
        
        setSafeAreaInsets(view.safeAreaInsets)
    }
    
    // MARK:- Private methods
    
    private func updateCornerRadii() {
        let newCornerRadius: CGFloat = {
            if shouldShowBarsOnlyOniPhoneX && !isiPhoneX {
                return 0
            }
            
            switch cornerRadius {
                
            case .standard:
                if isiPhoneX {
                    return 22
                } else {
                    return 8
                }
                
            case .custom(let customValue):
                return customValue
            
            }
        }()
        
        cornerViews.forEach {
            $0.cornerRadius = newCornerRadius
        }
    }
    
    private func setSafeAreaInsets(_ insets: UIEdgeInsets) {
        let safeViewFrame: CGRect = {
            if shouldShowBarsOnlyOniPhoneX && !isiPhoneX {
                return bounds
            } else {
                return bounds.insetBy(insets: insets)
            }
        }()
        
        UIView.animate(withDuration: 0.1) { [unowned self] in
            self.safeView.frame = safeViewFrame
        }
    }
    
    private func updateRootViewController(from oldValue: UIViewController?, to newValue: UIViewController?) {
        if let oldValue = oldValue {
            oldValue.view.removeObserver(self, forKeyPath: safeAreaInsetsKeyPath)
        }
        
        if let newValue = newValue {
            newValue.view.addObserver(self, forKeyPath: safeAreaInsetsKeyPath, options: [.initial], context: nil)
        }
    }
    
}

<commit_msg>Updated the bars to be based on left/right instead of leading/trailing anchors<commit_after>//
//  NotchKitWindow.swift
//  NotchKit
//
//  Created by <NAME> on 16/09/17.
//  Copyright © 2017 <NAME>. All rights reserved.
//

import UIKit

public final class NotchKitWindow: UIWindow {
    
    // MARK:- Types
    
    public enum CornerRadius {
        case standard
        case custom(CGFloat)
    }
    
    // MARK:- Public variables
    
    /// The corner radius for the rounded view. It can be set to a custom value,
    /// or to use the standard value which sets the corner radius appropriately
    /// for the screen size
    public var cornerRadius: CornerRadius = .standard {
        didSet { updateCornerRadii() }
    }
    
    /// A Bool indicating whether bars are shown only on the iPhone X.
    ///
    /// When this property's value is true, black bars to cover the notch and
    /// the home indicator are shown only on the iPhone X.
    ///
    /// When this property's value is false, black bars and curved corners are
    /// shown on all devices
    ///
    /// The default value of this property is `false`
    public var shouldShowBarsOnlyOniPhoneX = false {
        didSet { layoutSubviews() }
    }
    
    public override var rootViewController: UIViewController? {
        didSet {
            updateRootViewController(from: oldValue, to: rootViewController)
        }
    }
    
    // MARK:- Private variables
    
    private let safeAreaInsetsKeyPath = "safeAreaInsets"
    
    private var isiPhoneX: Bool {
        return screen.nativeBounds.size == CGSize(width: 1125, height: 2436)
    }
    
    // MARK:- View hierarchy
    
    private let safeView = UIView()
    
    private let topBarView = UIView()
    private let leftBarView = UIView()
    private let rightBarView = UIView()
    private let bottomBarView = UIView()
    
    private let topLeftCorner = CornerView()
    private let topRightCorner = CornerView()
    private let bottomLeftCorner = CornerView()
    private let bottomRightCorner = CornerView()
    
    private var barViews: [UIView] {
        return [topBarView, leftBarView, rightBarView, bottomBarView]
    }
    
    private var cornerViews: [CornerView] {
        return [topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner]
    }
    
    // MARK:- Initializers
    
    public override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }
    
    public override func awakeFromNib() {
        super.awakeFromNib()
        setup()
    }
    
    private func setup() {
        safeView.isUserInteractionEnabled = false
        addSubview(safeView)
        
        barViews.forEach { bar in
            bar.backgroundColor = .black
            bar.translatesAutoresizingMaskIntoConstraints = false
            safeView.addSubview(bar)
        }
        
        NSLayoutConstraint.activate([
            topBarView.topAnchor.constraint(equalTo: topAnchor),
            topBarView.bottomAnchor.constraint(equalTo: safeView.topAnchor),
            topBarView.leftAnchor.constraint(equalTo: leftAnchor),
            topBarView.rightAnchor.constraint(equalTo: rightAnchor),
            
            leftBarView.topAnchor.constraint(equalTo: topAnchor),
            leftBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            leftBarView.leftAnchor.constraint(equalTo: leftAnchor),
            leftBarView.rightAnchor.constraint(equalTo: safeView.leftAnchor),
            
            rightBarView.topAnchor.constraint(equalTo: topAnchor),
            rightBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            rightBarView.leftAnchor.constraint(equalTo: safeView.rightAnchor),
            rightBarView.rightAnchor.constraint(equalTo: rightAnchor),
            
            bottomBarView.topAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomBarView.bottomAnchor.constraint(equalTo: bottomAnchor),
            bottomBarView.leftAnchor.constraint(equalTo: leftAnchor),
            bottomBarView.rightAnchor.constraint(equalTo: rightAnchor)
        ])
        
        topLeftCorner.corner = .topLeft
        topRightCorner.corner = .topRight
        bottomLeftCorner.corner = .bottomLeft
        bottomRightCorner.corner = .bottomRight
        
        cornerViews.forEach { corner in
            corner.cornerRadius = 44
            corner.translatesAutoresizingMaskIntoConstraints = false
            safeView.addSubview(corner)
        }
        
        NSLayoutConstraint.activate([
            topLeftCorner.topAnchor.constraint(equalTo: safeView.topAnchor),
            topLeftCorner.leftAnchor.constraint(equalTo: safeView.leftAnchor),
            
            topRightCorner.topAnchor.constraint(equalTo: safeView.topAnchor),
            topRightCorner.rightAnchor.constraint(equalTo: safeView.rightAnchor),
            
            bottomLeftCorner.bottomAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomLeftCorner.leftAnchor.constraint(equalTo: safeView.leftAnchor),
            
            bottomRightCorner.bottomAnchor.constraint(equalTo: safeView.bottomAnchor),
            bottomRightCorner.rightAnchor.constraint(equalTo: safeView.rightAnchor)
        ])
    }
    
    deinit {
        updateRootViewController(from: rootViewController, to: nil)
    }
    
    // MARK:- UIView methods
    
    public override func layoutSubviews() {
        super.layoutSubviews()
        bringSubview(toFront: safeView)
        updateCornerRadii()
    }
    
    // MARK:- Key value observation
    
    public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard keyPath == safeAreaInsetsKeyPath,
              let view = object as? UIView,
              view.isEqual(rootViewController?.view)
        else {
            return
        }
        
        setSafeAreaInsets(view.safeAreaInsets)
    }
    
    // MARK:- Private methods
    
    private func updateCornerRadii() {
        let newCornerRadius: CGFloat = {
            if shouldShowBarsOnlyOniPhoneX && !isiPhoneX {
                return 0
            }
            
            switch cornerRadius {
                
            case .standard:
                if isiPhoneX {
                    return 22
                } else {
                    return 8
                }
                
            case .custom(let customValue):
                return customValue
            
            }
        }()
        
        cornerViews.forEach {
            $0.cornerRadius = newCornerRadius
        }
    }
    
    private func setSafeAreaInsets(_ insets: UIEdgeInsets) {
        let safeViewFrame: CGRect = {
            if shouldShowBarsOnlyOniPhoneX && !isiPhoneX {
                return bounds
            } else {
                return bounds.insetBy(insets: insets)
            }
        }()
        
        UIView.animate(withDuration: 0.1) { [unowned self] in
            self.safeView.frame = safeViewFrame
        }
    }
    
    private func updateRootViewController(from oldValue: UIViewController?, to newValue: UIViewController?) {
        if let oldValue = oldValue {
            oldValue.view.removeObserver(self, forKeyPath: safeAreaInsetsKeyPath)
        }
        
        if let newValue = newValue {
            newValue.view.addObserver(self, forKeyPath: safeAreaInsetsKeyPath, options: [.initial], context: nil)
        }
    }
    
}


{'fraction_non_alphanumeric': 0.07758114020766668, 'fraction_numerical': 0.0035264154639848494, 'mean_word_length': 2.033676703645008, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1179946', 'n_tokens_mistral': 4139, 'n_tokens_neox': 3982, 'n_words': 917}