Re-add navigation bar
This commit is contained in:
parent
256cb0958e
commit
d3c196949e
|
@ -19,17 +19,33 @@ class BrowserNavigationController: UIViewController {
|
||||||
private var currentBrowserVC: BrowserWebViewController!
|
private var currentBrowserVC: BrowserWebViewController!
|
||||||
|
|
||||||
private var browserContainer: UIView!
|
private var browserContainer: UIView!
|
||||||
|
private var navBarView: NavigationBarView!
|
||||||
private var toolbarView: ToolbarView!
|
private var toolbarView: ToolbarView!
|
||||||
|
|
||||||
private var gestureState: GestureState?
|
private var gestureState: GestureState?
|
||||||
private var trackingScroll = false
|
private var trackingScroll = false
|
||||||
|
private var scrollStartedBelowEnd = false
|
||||||
private var prevScrollViewContentOffset: CGPoint?
|
private var prevScrollViewContentOffset: CGPoint?
|
||||||
private var toolbarOffset: CGFloat = 0 {
|
private var toolbarOffset: CGFloat = 0 {
|
||||||
didSet {
|
didSet {
|
||||||
toolbarView.transform = CGAffineTransform(translationX: 0, y: toolbarOffset)
|
let realOffset = toolbarOffset * max(toolbarView.bounds.height, navBarView.bounds.height)
|
||||||
|
toolbarView.transform = CGAffineTransform(translationX: 0, y: realOffset)
|
||||||
|
navBarView.transform = CGAffineTransform(translationX: 0, y: -realOffset)
|
||||||
|
|
||||||
|
if (oldValue <= 0.5 && toolbarOffset > 0.5) || (oldValue > 0.5 && toolbarOffset <= 0.5) {
|
||||||
|
setNeedsStatusBarAppearanceUpdate()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var prefersStatusBarHidden: Bool {
|
||||||
|
toolbarOffset > 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
|
||||||
|
.slide
|
||||||
|
}
|
||||||
|
|
||||||
private var cancellables = [AnyCancellable]()
|
private var cancellables = [AnyCancellable]()
|
||||||
|
|
||||||
init(navigator: NavigationManager) {
|
init(navigator: NavigationManager) {
|
||||||
|
@ -55,6 +71,15 @@ class BrowserNavigationController: UIViewController {
|
||||||
currentBrowserVC.scrollViewDelegate = self
|
currentBrowserVC.scrollViewDelegate = self
|
||||||
embedChild(currentBrowserVC, in: browserContainer)
|
embedChild(currentBrowserVC, in: browserContainer)
|
||||||
|
|
||||||
|
navBarView = NavigationBarView(navigator: navigator)
|
||||||
|
navBarView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(navBarView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
navBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
navBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
|
navBarView.topAnchor.constraint(equalTo: view.topAnchor),
|
||||||
|
])
|
||||||
|
|
||||||
toolbarView = ToolbarView(navigator: navigator)
|
toolbarView = ToolbarView(navigator: navigator)
|
||||||
toolbarView.showShareSheet = self.showShareSheet
|
toolbarView.showShareSheet = self.showShareSheet
|
||||||
toolbarView.showPreferences = self.showPreferences
|
toolbarView.showPreferences = self.showPreferences
|
||||||
|
@ -86,8 +111,14 @@ class BrowserNavigationController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setBrowserVCSafeAreaInsets(_ vc: BrowserWebViewController) {
|
private func setBrowserVCSafeAreaInsets(_ vc: BrowserWebViewController) {
|
||||||
guard let toolbarView = toolbarView else { return }
|
guard let toolbarView = toolbarView,
|
||||||
vc.additionalSafeAreaInsets = UIEdgeInsets(top: 0, left: 0, bottom: toolbarView.bounds.height - view.safeAreaInsets.bottom - toolbarOffset, right: 0)
|
let navBarView = navBarView else { return }
|
||||||
|
vc.additionalSafeAreaInsets = UIEdgeInsets(
|
||||||
|
top: navBarView.bounds.height - view.safeAreaInsets.top,
|
||||||
|
left: 0,
|
||||||
|
bottom: toolbarView.bounds.height - view.safeAreaInsets.bottom,
|
||||||
|
right: 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func onNavigate(_ operation: NavigationManager.Operation) {
|
private func onNavigate(_ operation: NavigationManager.Operation) {
|
||||||
|
@ -118,6 +149,11 @@ class BrowserNavigationController: UIViewController {
|
||||||
currentBrowserVC = newVC
|
currentBrowserVC = newVC
|
||||||
currentBrowserVC.scrollViewDelegate = self
|
currentBrowserVC.scrollViewDelegate = self
|
||||||
embedChild(newVC, in: browserContainer)
|
embedChild(newVC, in: browserContainer)
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseInOut) {
|
||||||
|
self.toolbarOffset = 0
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private let startEdgeNavigationSwipeDistance: CGFloat = 75
|
private let startEdgeNavigationSwipeDistance: CGFloat = 75
|
||||||
|
@ -253,6 +289,7 @@ extension BrowserNavigationController: UIScrollViewDelegate {
|
||||||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||||
trackingScroll = true
|
trackingScroll = true
|
||||||
prevScrollViewContentOffset = scrollView.contentOffset
|
prevScrollViewContentOffset = scrollView.contentOffset
|
||||||
|
scrollStartedBelowEnd = scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.bounds.height + scrollView.safeAreaInsets.bottom)
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
@ -262,19 +299,18 @@ extension BrowserNavigationController: UIScrollViewDelegate {
|
||||||
|
|
||||||
let delta = scrollView.contentOffset.y - prevOffset.y
|
let delta = scrollView.contentOffset.y - prevOffset.y
|
||||||
|
|
||||||
let belowEnd = scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.bounds.height + scrollView.safeAreaInsets.bottom
|
let belowEnd = scrollView.contentOffset.y > (scrollView.contentSize.height - scrollView.bounds.height + scrollView.safeAreaInsets.bottom)
|
||||||
|
|
||||||
if belowEnd {
|
if belowEnd {
|
||||||
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseInOut) {
|
if scrollStartedBelowEnd {
|
||||||
self.toolbarOffset = 0
|
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseInOut) {
|
||||||
} completion: { (_) in
|
self.toolbarOffset = 0
|
||||||
self.setBrowserVCSafeAreaInsets(self.currentBrowserVC)
|
}
|
||||||
|
trackingScroll = false
|
||||||
}
|
}
|
||||||
trackingScroll = false
|
} else if delta > 0 || (delta < 0 && toolbarOffset < 1) {
|
||||||
} else if delta > 0 || (delta < 0 && toolbarOffset < toolbarView.bounds.height) {
|
let normalizedDelta = delta / max(toolbarView.bounds.height, navBarView.bounds.height)
|
||||||
toolbarOffset = max(0, min(toolbarView.bounds.height, toolbarOffset + delta))
|
toolbarOffset = max(0, min(1, toolbarOffset + normalizedDelta))
|
||||||
|
|
||||||
setBrowserVCSafeAreaInsets(currentBrowserVC)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +322,7 @@ extension BrowserNavigationController: UIScrollViewDelegate {
|
||||||
if velocity.y < 0 {
|
if velocity.y < 0 {
|
||||||
finalOffset = 0
|
finalOffset = 0
|
||||||
} else {
|
} else {
|
||||||
finalOffset = toolbarView.bounds.height
|
finalOffset = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut) {
|
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseOut) {
|
||||||
|
|
|
@ -6,15 +6,80 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import BrowserCore
|
||||||
|
import Combine
|
||||||
|
|
||||||
class NavigationBarView: UIView {
|
class NavigationBarView: UIView {
|
||||||
|
|
||||||
/*
|
let navigator: NavigationManager
|
||||||
// Only override draw() if you perform custom drawing.
|
|
||||||
// An empty implementation adversely affects performance during animation.
|
private var border: UIView!
|
||||||
override func draw(_ rect: CGRect) {
|
private var textField: UITextField!
|
||||||
// Drawing code
|
|
||||||
|
private var cancellables = [AnyCancellable]()
|
||||||
|
|
||||||
|
init(navigator: NavigationManager) {
|
||||||
|
self.navigator = navigator
|
||||||
|
|
||||||
|
super.init(frame: .zero)
|
||||||
|
|
||||||
|
backgroundColor = .systemBackground
|
||||||
|
|
||||||
|
border = UIView()
|
||||||
|
border.backgroundColor = UIColor(white: traitCollection.userInterfaceStyle == .dark ? 0.25 : 0.75, alpha: 1)
|
||||||
|
border.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
addSubview(border)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
border.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
|
border.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||||
|
border.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
|
border.heightAnchor.constraint(equalToConstant: 1),
|
||||||
|
])
|
||||||
|
|
||||||
|
textField = UITextField()
|
||||||
|
textField.text = navigator.displayURL
|
||||||
|
textField.borderStyle = .roundedRect
|
||||||
|
textField.keyboardType = .URL
|
||||||
|
textField.autocapitalizationType = .none
|
||||||
|
textField.autocorrectionType = .no
|
||||||
|
textField.addTarget(self, action: #selector(commitURL), for: .editingDidEnd)
|
||||||
|
textField.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
addSubview(textField)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
textField.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
|
||||||
|
textField.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
|
||||||
|
textField.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor),
|
||||||
|
textField.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -9),
|
||||||
|
])
|
||||||
|
|
||||||
|
navigator.$currentURL
|
||||||
|
.sink { (newURL) in
|
||||||
|
// can't use navigator.displayURL because the publisher fires before the underlying value is updated, so the displayURL getter returns the old value
|
||||||
|
var components = URLComponents(url: newURL, resolvingAgainstBaseURL: false)!
|
||||||
|
if components.port == 1965 {
|
||||||
|
components.port = nil
|
||||||
|
}
|
||||||
|
self.textField.text = components.string!
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||||
|
super.traitCollectionDidChange(previousTraitCollection)
|
||||||
|
|
||||||
|
border.backgroundColor = UIColor(white: traitCollection.userInterfaceStyle == .dark ? 0.25 : 0.75, alpha: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func commitURL() {
|
||||||
|
if let text = textField.text, let url = URL(string: text) {
|
||||||
|
navigator.changeURL(url)
|
||||||
|
} else {
|
||||||
|
textField.text = navigator.displayURL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
D69F00AC24BE9DD300E37622 /* GeminiDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */; };
|
D69F00AC24BE9DD300E37622 /* GeminiDataTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AB24BE9DD300E37622 /* GeminiDataTask.swift */; };
|
||||||
D69F00AE24BEA29100E37622 /* GeminiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AD24BEA29100E37622 /* GeminiResponse.swift */; };
|
D69F00AE24BEA29100E37622 /* GeminiResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69F00AD24BEA29100E37622 /* GeminiResponse.swift */; };
|
||||||
D6BC9AB3258E8E13008652BC /* ToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9AB2258E8E13008652BC /* ToolbarView.swift */; };
|
D6BC9AB3258E8E13008652BC /* ToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9AB2258E8E13008652BC /* ToolbarView.swift */; };
|
||||||
|
D6BC9ABC258E9862008652BC /* NavigationBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9ABB258E9862008652BC /* NavigationBarView.swift */; };
|
||||||
D6DA5783252396030048B65A /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DA5782252396030048B65A /* View+Extensions.swift */; };
|
D6DA5783252396030048B65A /* View+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DA5782252396030048B65A /* View+Extensions.swift */; };
|
||||||
D6E1529824BFAAA400FDF9D3 /* BrowserWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */; };
|
D6E1529824BFAAA400FDF9D3 /* BrowserWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */; };
|
||||||
D6E1529924BFAAA400FDF9D3 /* BrowserWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */; };
|
D6E1529924BFAAA400FDF9D3 /* BrowserWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */; };
|
||||||
|
@ -323,6 +324,7 @@
|
||||||
D69F00AD24BEA29100E37622 /* GeminiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiResponse.swift; sourceTree = "<group>"; };
|
D69F00AD24BEA29100E37622 /* GeminiResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiResponse.swift; sourceTree = "<group>"; };
|
||||||
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationManager.swift; sourceTree = "<group>"; };
|
D69F00AF24BEA84D00E37622 /* NavigationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationManager.swift; sourceTree = "<group>"; };
|
||||||
D6BC9AB2258E8E13008652BC /* ToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarView.swift; sourceTree = "<group>"; };
|
D6BC9AB2258E8E13008652BC /* ToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarView.swift; sourceTree = "<group>"; };
|
||||||
|
D6BC9ABB258E9862008652BC /* NavigationBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBarView.swift; sourceTree = "<group>"; };
|
||||||
D6DA5782252396030048B65A /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
|
D6DA5782252396030048B65A /* View+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extensions.swift"; sourceTree = "<group>"; };
|
||||||
D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserWindowController.swift; sourceTree = "<group>"; };
|
D6E1529624BFAAA400FDF9D3 /* BrowserWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserWindowController.swift; sourceTree = "<group>"; };
|
||||||
D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrowserWindowController.xib; sourceTree = "<group>"; };
|
D6E1529724BFAAA400FDF9D3 /* BrowserWindowController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BrowserWindowController.xib; sourceTree = "<group>"; };
|
||||||
|
@ -588,6 +590,7 @@
|
||||||
D688F632258B09BB003A0A73 /* TrackpadScrollGestureRecognizer.swift */,
|
D688F632258B09BB003A0A73 /* TrackpadScrollGestureRecognizer.swift */,
|
||||||
D688F662258C2479003A0A73 /* UIViewController+Children.swift */,
|
D688F662258C2479003A0A73 /* UIViewController+Children.swift */,
|
||||||
D6BC9AB2258E8E13008652BC /* ToolbarView.swift */,
|
D6BC9AB2258E8E13008652BC /* ToolbarView.swift */,
|
||||||
|
D6BC9ABB258E9862008652BC /* NavigationBarView.swift */,
|
||||||
D691A6762522382E00348C4B /* BrowserViewController.swift */,
|
D691A6762522382E00348C4B /* BrowserViewController.swift */,
|
||||||
D6E152A824BFFDF500FDF9D3 /* ContentView.swift */,
|
D6E152A824BFFDF500FDF9D3 /* ContentView.swift */,
|
||||||
D691A68625223A4600348C4B /* NavigationBar.swift */,
|
D691A68625223A4600348C4B /* NavigationBar.swift */,
|
||||||
|
@ -1120,6 +1123,7 @@
|
||||||
D688F663258C2479003A0A73 /* UIViewController+Children.swift in Sources */,
|
D688F663258C2479003A0A73 /* UIViewController+Children.swift in Sources */,
|
||||||
D691A64E25217C6F00348C4B /* Preferences.swift in Sources */,
|
D691A64E25217C6F00348C4B /* Preferences.swift in Sources */,
|
||||||
D6E152A924BFFDF500FDF9D3 /* ContentView.swift in Sources */,
|
D6E152A924BFFDF500FDF9D3 /* ContentView.swift in Sources */,
|
||||||
|
D6BC9ABC258E9862008652BC /* NavigationBarView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue