Re-add navigation bar

This commit is contained in:
Shadowfacts 2020-12-19 22:43:43 -05:00
parent 256cb0958e
commit d3c196949e
3 changed files with 125 additions and 20 deletions

View File

@ -19,16 +19,32 @@ 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]()
@ -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 {
if scrollStartedBelowEnd {
UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseInOut) { UIView.animate(withDuration: 0.15, delay: 0, options: .curveEaseInOut) {
self.toolbarOffset = 0 self.toolbarOffset = 0
} completion: { (_) in
self.setBrowserVCSafeAreaInsets(self.currentBrowserVC)
} }
trackingScroll = false trackingScroll = false
} else if delta > 0 || (delta < 0 && toolbarOffset < toolbarView.bounds.height) { }
toolbarOffset = max(0, min(toolbarView.bounds.height, toolbarOffset + delta)) } else if delta > 0 || (delta < 0 && toolbarOffset < 1) {
let normalizedDelta = delta / max(toolbarView.bounds.height, navBarView.bounds.height)
setBrowserVCSafeAreaInsets(currentBrowserVC) toolbarOffset = max(0, min(1, toolbarOffset + normalizedDelta))
} }
} }
@ -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) {

View File

@ -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
}
} }
*/
} }

View File

@ -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;
}; };