// // URLBar.swift // SBrowser // // Created by James Magahern on 7/23/20. // import UIKit class URLBar: UIView { let textField = UITextField(frame: .zero) let refreshButton = UIButton(frame: .zero) public enum LoadProgress { case complete case loading(progress: Double) } public var loadProgress: LoadProgress = .complete { didSet { updateProgressIndicator() } } private let backgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemThickMaterial)) private let progressIndicatorView = ProgressIndicatorView() private let refreshImage = UIImage(systemName: "arrow.clockwise") private let stopImage = UIImage(systemName: "xmark") convenience init() { self.init(frame: .zero) backgroundColor = .clear backgroundView.layer.masksToBounds = true backgroundView.layer.cornerRadius = 8 backgroundView.layer.borderWidth = 1 backgroundView.layer.borderColor = UIColor.systemFill.cgColor backgroundView.isUserInteractionEnabled = false addSubview(backgroundView) backgroundView.contentView.addSubview(progressIndicatorView) textField.backgroundColor = .clear textField.textContentType = .URL textField.keyboardType = .webSearch textField.autocorrectionType = .no textField.autocapitalizationType = .none textField.font = .systemFont(ofSize: 14.0) textField.clearingBehavior = .clearOnInsertionAndShowSelectionTint textField.clearButtonMode = .whileEditing addSubview(textField) textField.addAction(.init(handler: { _ in self.refreshButton.isHidden = self.textField.isFirstResponder }), for: [ .editingDidBegin, .editingDidEnd ]) refreshButton.tintColor = .secondaryLabel refreshButton.setImage(refreshImage, for: .normal) addSubview(refreshButton) } private func updateProgressIndicator() { UIView.animate(withDuration: 0.4) { switch self.loadProgress { case .complete: self.refreshButton.setImage(self.refreshImage, for: .normal) self.progressIndicatorView.progress = 1.0 UIView.animate(withDuration: 0.5, delay: 0.5, options: AnimationOptions()) { self.progressIndicatorView.alpha = 0.0 } completion: { _ in // Reset back to zero self.progressIndicatorView.progress = 0.0 } case .loading(let progress): self.refreshButton.setImage(self.stopImage, for: .normal) self.progressIndicatorView.progress = progress self.progressIndicatorView.alpha = 1.0 } } } override var intrinsicContentSize: CGSize { let preferredHeight = CGFloat(34) return CGSize(width: 1000.0, height: preferredHeight) } override func layoutSubviews() { super.layoutSubviews() backgroundView.frame = bounds progressIndicatorView.frame = backgroundView.contentView.bounds textField.frame = bounds.insetBy(dx: 6.0, dy: 0) let refreshButtonSize = CGSize(width: textField.frame.height, height: textField.frame.height) refreshButton.frame = CGRect(origin: CGPoint(x: bounds.width - refreshButtonSize.width, y: 0), size: refreshButtonSize) } } class ProgressIndicatorView: UIView { public var progress: Double = 0.0 { didSet { layoutSubviews() } } private let progressFillView = UIView(frame: .zero) convenience init() { self.init(frame: .zero) progressFillView.backgroundColor = .systemBlue progressFillView.alpha = 0.3 addSubview(progressFillView) } override func layoutSubviews() { super.layoutSubviews() let width = CGFloat(progress) * bounds.width progressFillView.frame = CGRect(origin: .zero, size: CGSize(width: width, height: bounds.height)) } }