Files
Attractor/SBrowser/Browser View/BrowserView.swift

110 lines
4.3 KiB
Swift
Raw Normal View History

//
// BrowserView.swift
// SBrowser
//
// Created by James Magahern on 7/21/20.
//
2020-07-24 19:26:35 -07:00
import Combine
import UIKit
import WebKit
class BrowserView: UIView
{
2020-07-29 14:16:25 -07:00
let titlebarView = TitlebarView()
2020-07-24 19:26:35 -07:00
var toolbarView: ToolbarView? {
didSet { addSubview(toolbarView!) }
}
var webView: WKWebView? {
2020-07-24 19:26:35 -07:00
didSet {
oldValue?.removeFromSuperview()
2020-07-24 19:26:35 -07:00
if let toolbarView = toolbarView {
insertSubview(webView!, belowSubview: toolbarView)
} else {
addSubview(webView!)
}
}
}
2020-07-24 19:26:35 -07:00
var keyboardWillShowObserver: AnyCancellable?
var keyboardWillHideObserver: AnyCancellable?
var keyboardLayoutOffset: CGFloat = 0 { didSet { setNeedsLayout() } }
convenience init() {
self.init(frame: .zero)
2020-07-29 14:16:25 -07:00
addSubview(titlebarView)
keyboardWillShowObserver = NotificationCenter.default.publisher(for: UIWindow.keyboardWillShowNotification).sink { [weak self] notification in
self?.adjustOffsetForKeyboardNotification(userInfo: notification.userInfo!)
2020-07-24 19:26:35 -07:00
}
keyboardWillHideObserver = NotificationCenter.default.publisher(for: UIWindow.keyboardWillHideNotification).sink { [weak self] notification in
self?.adjustOffsetForKeyboardNotification(userInfo: notification.userInfo!)
2020-07-24 19:26:35 -07:00
}
}
private func adjustOffsetForKeyboardNotification(userInfo: [AnyHashable : Any]) {
guard let keyboardEndFrame = userInfo[UIWindow.keyboardFrameEndUserInfoKey] as? CGRect else { return }
guard let animationDuration = userInfo[UIWindow.keyboardAnimationDurationUserInfoKey] as? TimeInterval else { return }
guard let animationCurve = userInfo[UIWindow.keyboardAnimationCurveUserInfoKey] as? Int else { return }
let animationOptions: UIView.AnimationOptions = { curve -> UIView.AnimationOptions in
switch UIView.AnimationCurve(rawValue: curve) {
case .easeIn: return .curveEaseIn
case .easeOut: return .curveEaseOut
case .easeInOut: return .curveEaseInOut
default: return .init()
}
}(animationCurve)
keyboardLayoutOffset = bounds.height - keyboardEndFrame.minY
UIView.animate(withDuration: animationDuration, delay: 0.0, options: animationOptions, animations: { self.layoutIfNeeded() }, completion: nil)
}
override func layoutSubviews() {
super.layoutSubviews()
webView?.frame = bounds
2020-07-24 19:26:35 -07:00
2020-07-29 18:34:46 -07:00
var webViewContentInset = UIEdgeInsets()
2020-07-29 14:16:25 -07:00
bringSubviewToFront(titlebarView)
var titlebarHeight: CGFloat = 24.0
titlebarHeight += safeAreaInsets.top
titlebarView.frame = CGRect(origin: .zero, size: CGSize(width: bounds.width, height: titlebarHeight))
2020-07-29 18:34:46 -07:00
webViewContentInset.top += titlebarView.frame.height
if let toolbarView = toolbarView {
var toolbarSize = toolbarView.sizeThatFits(bounds.size)
// Compact: toolbar is at the bottom
if traitCollection.horizontalSizeClass == .compact {
var bottomOffset: CGFloat = 0.0
if keyboardLayoutOffset == 0 {
toolbarSize.height += safeAreaInsets.bottom
} else if toolbarView.urlBar?.textField.isFirstResponder ?? false {
bottomOffset = keyboardLayoutOffset
}
toolbarView.bounds = CGRect(origin: .zero, size: toolbarSize)
toolbarView.center = CGPoint(x: bounds.center.x, y: bounds.maxY - (toolbarView.bounds.height / 2) - bottomOffset)
webViewContentInset.bottom += toolbarView.frame.height
} else {
// Regular: toolbar is at the top
2020-07-29 19:24:05 -07:00
toolbarView.frame = CGRect(origin: CGPoint(x: 0.0, y: titlebarView.frame.maxY), size: toolbarSize)
2020-07-29 18:34:46 -07:00
webViewContentInset.top += toolbarView.frame.height
}
}
2020-07-29 14:16:25 -07:00
// Fix web view content insets
webView?.scrollView.automaticallyAdjustsScrollIndicatorInsets = false
webView?.scrollView.contentInset = webViewContentInset.subtracting(safeAreaInsets)
2020-07-29 14:16:25 -07:00
webView?.scrollView.scrollIndicatorInsets = webViewContentInset
}
}