Skip to content

Commit

Permalink
fix page position on navigation (#2330)
Browse files Browse the repository at this point in the history
  • Loading branch information
brindy authored Jan 15, 2024
1 parent 6ad3a78 commit 8b94de5
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
Expand Down
15 changes: 6 additions & 9 deletions DuckDuckGo/BarsAnimator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ class BarsAnimator {
let ratio = calculateTransitionRatio(for: scrollView.contentOffset.y)
delegate?.setBarsVisibility(1.0 - ratio, animated: false)
transitionProgress = ratio

var offset = scrollView.contentOffset
offset.y = transitionStartPosY
scrollView.contentOffset = offset
}

private func transitioningAndScrolling(in scrollView: UIScrollView) {
Expand All @@ -103,10 +99,6 @@ class BarsAnimator {

delegate?.setBarsVisibility(1.0 - ratio, animated: false)
transitionProgress = ratio

var offset = scrollView.contentOffset
offset.y = transitionStartPosY
scrollView.contentOffset = offset
}

private func hiddenAndScrolling(in scrollView: UIScrollView) {
Expand Down Expand Up @@ -139,7 +131,12 @@ class BarsAnimator {
let cumulativeDistance = (barsHeight * transitionProgress) + distance
let normalizedDistance = max(cumulativeDistance, 0)

return min(normalizedDistance / barsHeight, 1.0)
// We used to fix the scroll position in place as the transition happened
// but now the bars disappear too. This adjusts for that.
let transitionSpeed = 0.5

let ratio = min(normalizedDistance / barsHeight * transitionSpeed, 1.0)
return ratio
}

func didFinishScrolling(in scrollView: UIScrollView, velocity: CGFloat) {
Expand Down
1 change: 0 additions & 1 deletion DuckDuckGo/BrowserChromeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ protocol BrowserChromeDelegate: AnyObject {
class BrowserChromeManager: NSObject, UIScrollViewDelegate {

struct Constants {
static let dragThreshold: CGFloat = 30
static let zoomThreshold: CGFloat = 0.1

static let contentSizeKVOKey = "contentSize"
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/BrowsingMenu/BrowsingMenuAnimator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ final class BrowsingMenuAnimator: NSObject, UIViewControllerAnimatedTransitionin
transitionContext.containerView.addSubview(fromSnapshot)
}

toViewController.bindConstraints(to: fromViewController.currentTab?.webView)
toViewController.bindConstraints(to: fromViewController.viewCoordinator.contentContainer)
toViewController.view.layoutIfNeeded()

let snapshot = toViewController.menuView.snapshotView(afterScreenUpdates: true)
Expand Down
20 changes: 10 additions & 10 deletions DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ final class BrowsingMenuViewController: UIViewController {

recalculatePreferredWidthConstraint()
recalculateHeightConstraints()
webView.map(recalculateMenuConstraints(with:))
guideView.map(recalculateMenuConstraints(with:))

if tableView.bounds.height < tableView.contentSize.height + tableView.contentInset.top + tableView.contentInset.bottom {
tableView.isScrollEnabled = true
Expand All @@ -166,12 +166,12 @@ final class BrowsingMenuViewController: UIViewController {
}
}

private weak var webView: UIView?
private var webViewFrameObserver: NSKeyValueObservation?
func bindConstraints(to webView: UIView?) {
self.webView = webView
self.webViewFrameObserver = webView?.observe(\.frame, options: [.initial]) { [weak self] webView, _ in
self?.recalculateMenuConstraints(with: webView)
private weak var guideView: UIView?
private var guideViewFrameObserver: NSKeyValueObservation?
func bindConstraints(to guideView: UIView?) {
self.guideView = guideView
self.guideViewFrameObserver = guideView?.observe(\.frame, options: [.initial]) { [weak self] guideView, _ in
self?.recalculateMenuConstraints(with: guideView)
}
}

Expand Down Expand Up @@ -205,9 +205,9 @@ final class BrowsingMenuViewController: UIViewController {
}
}

private func recalculateMenuConstraints(with webView: UIView) {
guard let frame = webView.superview?.convert(webView.frame, to: webView.window),
let windowBounds = webView.window?.bounds
private func recalculateMenuConstraints(with guideView: UIView) {
guard let frame = guideView.superview?.convert(guideView.frame, to: guideView.window),
let windowBounds = guideView.window?.bounds
else { return }

let isIPad = AppWidthObserver.shared.isLargeWidth
Expand Down
33 changes: 26 additions & 7 deletions DuckDuckGo/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class MainViewFactory {
extension MainViewFactory {

private func createViews() {
createWebViewContainer()
createLogoBackground()
createContentContainer()
createSuggestionTrayContainer()
Expand All @@ -64,13 +65,19 @@ extension MainViewFactory {
createProgressView()
createToolbar()
}

final class WebViewContainerView: UIView { }
private func createWebViewContainer() {
coordinator.webViewContainer = WebViewContainerView()
superview.addSubview(coordinator.webViewContainer)
}

private func createProgressView() {
coordinator.progress = ProgressView()
superview.addSubview(coordinator.progress)
}

class NavigationBarContainer: UIView { }
final class NavigationBarContainer: UIView { }
private func createNavigationBarContainer() {
coordinator.omniBar = OmniBar.loadFromXib()
coordinator.omniBar.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -79,31 +86,31 @@ extension MainViewFactory {
superview.addSubview(coordinator.navigationBarContainer)
}

class NotificationBarContainer: UIView { }
final class NotificationBarContainer: UIView { }
private func createNotificationBarContainer() {
coordinator.notificationBarContainer = NotificationBarContainer()
superview.addSubview(coordinator.notificationBarContainer)
}

class ContentContainer: UIView { }
final class ContentContainer: UIView { }
private func createContentContainer() {
coordinator.contentContainer = ContentContainer()
superview.addSubview(coordinator.contentContainer)
}

class StatusBackgroundView: UIView { }
final class StatusBackgroundView: UIView { }
private func createStatusBackground() {
coordinator.statusBackground = StatusBackgroundView()
superview.addSubview(coordinator.statusBackground)
}

class TabBarContainer: UIView { }
final class TabBarContainer: UIView { }
private func createTabBarContainer() {
coordinator.tabBarContainer = TabBarContainer()
superview.addSubview(coordinator.tabBarContainer)
}

class SuggestionTrayContainer: UIView { }
final class SuggestionTrayContainer: UIView { }
private func createSuggestionTrayContainer() {
coordinator.suggestionTrayContainer = SuggestionTrayContainer()
coordinator.suggestionTrayContainer.isHidden = true
Expand Down Expand Up @@ -136,7 +143,7 @@ extension MainViewFactory {
], animated: true)
}

class LogoBackgroundView: UIView { }
final class LogoBackgroundView: UIView { }
private func createLogoBackground() {
coordinator.logoContainer = LogoBackgroundView()
coordinator.logo = UIImageView(image: UIImage(named: "Logo"))
Expand All @@ -156,6 +163,7 @@ extension MainViewFactory {
extension MainViewFactory {

private func constrainViews() {
constrainWebViewContainer()
constrainLogoBackground()
constrainContentContainer()
constrainSuggestionTrayContainer()
Expand All @@ -166,6 +174,16 @@ extension MainViewFactory {
constrainProgress()
constrainToolbar()
}

private func constrainWebViewContainer() {
let webViewContainer = coordinator.webViewContainer!
NSLayoutConstraint.activate([
webViewContainer.constrainView(superview, by: .width),
webViewContainer.constrainView(superview, by: .height),
webViewContainer.constrainView(superview, by: .centerX),
webViewContainer.constrainView(superview, by: .centerY),
])
}

private func constrainProgress() {
let progress = coordinator.progress!
Expand Down Expand Up @@ -333,6 +351,7 @@ class MainViewCoordinator {
var toolbarFireButton: UIBarButtonItem!
var toolbarForwardButton: UIBarButtonItem!
var toolbarTabSwitcherButton: UIBarButtonItem!
var webViewContainer: UIView!

let constraints = Constraints()

Expand Down
67 changes: 54 additions & 13 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ class MainViewController: UIViewController {

// Skip SERP flow (focusing on autocomplete logic) and prepare for new navigation when selecting search bar
private var skipSERPFlow = true

private var keyboardHeight: CGFloat = 0.0

required init?(coder: NSCoder) {
fatalError("Use init?(code:")
Expand Down Expand Up @@ -430,6 +432,7 @@ class MainViewController: UIViewController {
@objc func onAddressBarPositionChanged() {
viewCoordinator.moveAddressBarToPosition(appSettings.currentAddressBarPosition)
refreshViewsBasedOnAddressBarPosition(appSettings.currentAddressBarPosition)
refreshWebViewContentInsets()
}

func refreshViewsBasedOnAddressBarPosition(_ position: AddressBarPosition) {
Expand Down Expand Up @@ -475,7 +478,8 @@ class MainViewController: UIViewController {
height = intersection.height

findInPageBottomLayoutConstraint.constant = height
currentTab?.webView.scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: height, right: 0)
keyboardHeight = height
refreshWebViewContentInsets()

if let suggestionsTray = suggestionTrayController {
let suggestionsFrameInView = suggestionsTray.view.convert(suggestionsTray.contentFrame, to: view)
Expand Down Expand Up @@ -640,7 +644,7 @@ class MainViewController: UIViewController {
guard let tab = tabManager.current(createIfNeeded: true) else {
fatalError("Unable to create tab")
}
addToView(tab: tab)
addToWebViewContainer(tab: tab)
refreshControls()
} else {
attachHomeScreen()
Expand Down Expand Up @@ -700,7 +704,7 @@ class MainViewController: UIViewController {
controller.chromeDelegate = self
controller.delegate = self

addToView(controller: controller)
addToContentContainer(controller: controller)

refreshControls()
syncService.scheduler.requestSyncImmediately()
Expand Down Expand Up @@ -849,7 +853,7 @@ class MainViewController: UIViewController {
private func addTab(url: URL?, inheritedAttribution: AdClickAttributionLogic.State?) {
let tab = tabManager.add(url: url, inheritedAttribution: inheritedAttribution)
dismissOmniBar()
addToView(tab: tab)
addToWebViewContainer(tab: tab)
}

func select(tabAt index: Int) {
Expand All @@ -863,7 +867,7 @@ class MainViewController: UIViewController {
if tab.link == nil {
attachHomeScreen()
} else {
addToView(tab: tab)
addToWebViewContainer(tab: tab)
refreshControls()
}
tabsBarController?.refresh(tabsModel: tabManager.model, scrollToSelected: true)
Expand All @@ -872,18 +876,29 @@ class MainViewController: UIViewController {
}
}

private func addToView(tab: TabViewController) {
private func addToWebViewContainer(tab: TabViewController) {
removeHomeScreen()
updateFindInPage()
currentTab?.progressWorker.progressBar = nil
currentTab?.chromeDelegate = nil
addToView(controller: tab)
currentTab?.webView.scrollView.contentInsetAdjustmentBehavior = .never

addChild(tab)
viewCoordinator.webViewContainer.subviews.forEach { $0.removeFromSuperview() }
viewCoordinator.webViewContainer.addSubview(tab.view)
tab.view.frame = self.viewCoordinator.webViewContainer.bounds
tab.didMove(toParent: self)

viewCoordinator.logoContainer.isHidden = true
viewCoordinator.contentContainer.isHidden = true

tab.progressWorker.progressBar = viewCoordinator.progress
chromeManager.attach(to: tab.webView.scrollView)
tab.chromeDelegate = self
}

private func addToView(controller: UIViewController) {
private func addToContentContainer(controller: UIViewController) {
viewCoordinator.contentContainer.isHidden = false
addChild(controller)
viewCoordinator.contentContainer.subviews.forEach { $0.removeFromSuperview() }
viewCoordinator.contentContainer.addSubview(controller.view)
Expand Down Expand Up @@ -1314,28 +1329,53 @@ extension MainViewController: BrowserChromeDelegate {
let updateBlock = {
self.updateToolbarConstant(percent)
self.updateNavBarConstant(percent)

self.view.layoutIfNeeded()

self.viewCoordinator.omniBar.alpha = percent
self.viewCoordinator.navigationBarContainer.alpha = percent
self.viewCoordinator.tabBarContainer.alpha = percent
self.viewCoordinator.toolbar.alpha = percent
}

if animated {
UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock)
UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock) { _ in
self.refreshWebViewContentInsets()
}
} else {
updateBlock()
self.refreshWebViewContentInsets()
}
}

func refreshWebViewContentInsets() {
guard let webView = currentTab?.webView else { return }

let top = viewCoordinator.statusBackground.frame.height
let bottom: CGFloat
if isToolbarHidden {
bottom = 0
} else if appSettings.currentAddressBarPosition.isBottom {
bottom = viewCoordinator.toolbar.frame.height
+ viewCoordinator.navigationBarContainer.frame.height
+ view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom
+ keyboardHeight
} else {
bottom = viewCoordinator.toolbar.frame.height
+ view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom
+ keyboardHeight
}

webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0)
}

func setNavigationBarHidden(_ hidden: Bool) {
if hidden { hideKeyboard() }

updateNavBarConstant(hidden ? 0 : 1.0)
viewCoordinator.omniBar.alpha = hidden ? 0 : 1
viewCoordinator.tabBarContainer.alpha = hidden ? 0 : 1
viewCoordinator.statusBackground.alpha = hidden ? 0 : 1

}

var canHideBars: Bool {
Expand Down Expand Up @@ -1693,7 +1733,7 @@ extension MainViewController: TabDelegate {
guard self.tabManager.model.tabs.contains(newTab.tabModel) else { return }

self.dismissOmniBar()
self.addToView(tab: newTab)
self.addToWebViewContainer(tab: newTab)
self.refreshOmniBar()
}

Expand Down Expand Up @@ -1797,6 +1837,7 @@ extension MainViewController: TabDelegate {

func showBars() {
chromeManager.reset()
refreshWebViewContentInsets()
}

func tabDidRequestFindInPage(tab: TabViewController) {
Expand Down
7 changes: 6 additions & 1 deletion DuckDuckGo/TabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,12 @@ extension TabViewController: WKNavigationDelegate {
DispatchQueue.main.async { [weak self] in
guard let webView = self?.webView,
webView.bounds.height > 0 && webView.bounds.width > 0 else { completion(nil); return }
UIGraphicsBeginImageContextWithOptions(webView.bounds.size, false, UIScreen.main.scale)

let size = CGSize(width: webView.frame.size.width,
height: webView.frame.size.height - webView.scrollView.contentInset.top - webView.scrollView.contentInset.bottom)

UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
UIGraphicsGetCurrentContext()?.translateBy(x: 0, y: -webView.scrollView.contentInset.top)
webView.drawHierarchy(in: webView.bounds, afterScreenUpdates: true)
if let jsAlertController = self?.jsAlertController {
jsAlertController.view.drawHierarchy(in: jsAlertController.view.bounds,
Expand Down
Loading

0 comments on commit 8b94de5

Please sign in to comment.