From 9dade03f79ec00cf0e96d74ced47e6b45d033425 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Tue, 9 Jan 2024 14:20:44 +0000 Subject: [PATCH 01/16] rough implementation --- DuckDuckGo/MainViewController.swift | 38 ++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 8818620158..f70055e56c 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -858,13 +858,25 @@ class MainViewController: UIViewController { updateFindInPage() currentTab?.progressWorker.progressBar = nil currentTab?.chromeDelegate = nil - addToView(controller: tab) + currentTab?.webView.scrollView.contentInsetAdjustmentBehavior = .never + + // addToView(controller: tab) + addChild(tab) + tab.willMove(toParent: self) + view.insertSubview(tab.view, at: 0) + tab.view.frame = self.view.frame + 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) { + viewCoordinator.contentContainer.isHidden = false addChild(controller) viewCoordinator.contentContainer.subviews.forEach { $0.removeFromSuperview() } viewCoordinator.contentContainer.addSubview(controller.view) @@ -1293,18 +1305,35 @@ 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 } + + func completion(_ finished: Bool) { + if self.appSettings.currentAddressBarPosition == .top { + let top: CGFloat = self.viewCoordinator.statusBackground.frame.height * percent + let bottom: CGFloat = (self.viewCoordinator.toolbar.frame.height * percent) + + self.view.safeAreaInsets.bottom + self.additionalSafeAreaInsets.bottom + print("***", bottom, top, percent, animated) + self.currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + } else { + let top: CGFloat = self.viewCoordinator.statusBackground.frame.height * percent + let bottom: CGFloat = ((self.viewCoordinator.toolbar.frame.height + self.viewCoordinator.navigationBarContainer.frame.height) * percent) + + self.view.safeAreaInsets.bottom + self.additionalSafeAreaInsets.bottom + print("***", bottom, top, percent, animated) + self.currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + } + } if animated { - UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock) + UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock, completion: completion) } else { updateBlock() + completion(true) } } @@ -1315,6 +1344,7 @@ extension MainViewController: BrowserChromeDelegate { viewCoordinator.omniBar.alpha = hidden ? 0 : 1 viewCoordinator.tabBarContainer.alpha = hidden ? 0 : 1 viewCoordinator.statusBackground.alpha = hidden ? 0 : 1 + } var canHideBars: Bool { From f2a3c8cabab5b29c84ded7953017aa4c0b3c442c Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Wed, 10 Jan 2024 12:34:04 +0000 Subject: [PATCH 02/16] experiment with not using zoom to adjust bars --- DuckDuckGo/BrowserChromeManager.swift | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/DuckDuckGo/BrowserChromeManager.swift b/DuckDuckGo/BrowserChromeManager.swift index 3f458dd74f..1946a86749 100644 --- a/DuckDuckGo/BrowserChromeManager.swift +++ b/DuckDuckGo/BrowserChromeManager.swift @@ -72,6 +72,10 @@ class BrowserChromeManager: NSObject, UIScrollViewDelegate { observation = nil } + func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { + print(#function) + } + private func scrollViewDidResizeContent(_ scrollView: UIScrollView) { if !canHideBars(for: scrollView) && animator.barsState != .revealed { animator.revealBars(animated: true) @@ -79,17 +83,17 @@ class BrowserChromeManager: NSObject, UIScrollViewDelegate { } func scrollViewDidScroll(_ scrollView: UIScrollView) { - guard !scrollView.isZooming else { return } - - guard dragging else { return } - guard canHideBars(for: scrollView) else { - if animator.barsState != .revealed { - animator.revealBars(animated: true) - } - return - } - - animator.didScroll(in: scrollView) +// guard !scrollView.isZooming else { return } +// +// guard dragging else { return } +// guard canHideBars(for: scrollView) else { +// if animator.barsState != .revealed { +// animator.revealBars(animated: true) +// } +// return +// } +// +// animator.didScroll(in: scrollView) } func scrollViewDidZoom(_ scrollView: UIScrollView) { From 612a0fc6ee0f4d8e075527c46b691be605bcab8e Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Wed, 10 Jan 2024 14:46:00 +0000 Subject: [PATCH 03/16] restore scrolling hide / show bars --- DuckDuckGo/BrowserChromeManager.swift | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/DuckDuckGo/BrowserChromeManager.swift b/DuckDuckGo/BrowserChromeManager.swift index 1946a86749..baa9f557cf 100644 --- a/DuckDuckGo/BrowserChromeManager.swift +++ b/DuckDuckGo/BrowserChromeManager.swift @@ -83,17 +83,17 @@ class BrowserChromeManager: NSObject, UIScrollViewDelegate { } func scrollViewDidScroll(_ scrollView: UIScrollView) { -// guard !scrollView.isZooming else { return } -// -// guard dragging else { return } -// guard canHideBars(for: scrollView) else { -// if animator.barsState != .revealed { -// animator.revealBars(animated: true) -// } -// return -// } -// -// animator.didScroll(in: scrollView) + guard !scrollView.isZooming else { return } + + guard dragging else { return } + guard canHideBars(for: scrollView) else { + if animator.barsState != .revealed { + animator.revealBars(animated: true) + } + return + } + + animator.didScroll(in: scrollView) } func scrollViewDidZoom(_ scrollView: UIScrollView) { From b5f90eed7b78258b65a1fb837ceb80d5c18978ae Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Wed, 10 Jan 2024 14:47:20 +0000 Subject: [PATCH 04/16] use content container as guide for the menu instead of webview, which is now a different size --- .../BrowsingMenu/BrowsingMenuAnimator.swift | 2 +- .../BrowsingMenuViewController.swift | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/DuckDuckGo/BrowsingMenu/BrowsingMenuAnimator.swift b/DuckDuckGo/BrowsingMenu/BrowsingMenuAnimator.swift index f5b5fbc572..6f1a53d398 100644 --- a/DuckDuckGo/BrowsingMenu/BrowsingMenuAnimator.swift +++ b/DuckDuckGo/BrowsingMenu/BrowsingMenuAnimator.swift @@ -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) diff --git a/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift b/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift index dec954d795..9752a564c1 100644 --- a/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift +++ b/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift @@ -157,7 +157,7 @@ final class BrowsingMenuViewController: UIViewController { recalculatePreferredWidthConstraint() recalculateHeightConstraints() - webView.map(recalculateMenuConstraints(with:)) + parent?.view.map(recalculateMenuConstraints(with:)) if tableView.bounds.height < tableView.contentSize.height + tableView.contentInset.top + tableView.contentInset.bottom { tableView.isScrollEnabled = true @@ -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) } } @@ -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 From 7156740e25b1591665bf6d4dd2faf21556c80955 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Thu, 11 Jan 2024 14:54:31 +0000 Subject: [PATCH 05/16] use the right size for preview image when transitioning back to web view --- DuckDuckGo/WebViewTransition.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/WebViewTransition.swift b/DuckDuckGo/WebViewTransition.swift index 8e123343ab..9167c270b1 100644 --- a/DuckDuckGo/WebViewTransition.swift +++ b/DuckDuckGo/WebViewTransition.swift @@ -152,7 +152,7 @@ class ToWebViewTransition: WebViewTransition { let preview = tabSwitcherViewController.previewsSource.preview(for: tab) if let preview = preview { imageView.frame = previewFrame(for: imageContainer.bounds.size, - preview: preview) + preview: preview) } else { imageView.frame = CGRect(origin: .zero, size: imageContainer.bounds.size) } @@ -165,10 +165,11 @@ class ToWebViewTransition: WebViewTransition { scrollIfOutsideViewport(collectionView: tabSwitcherViewController.collectionView, rowIndex: rowIndex, attributes: layoutAttr) UIView.animate(withDuration: TabSwitcherTransition.Constants.duration, animations: { - self.imageContainer.frame = webViewFrame + self.imageContainer.frame = mainViewController.viewCoordinator.contentContainer.frame self.imageContainer.layer.cornerRadius = 0 - self.imageView.frame = self.destinationImageFrame(for: webViewFrame.size, - preview: preview) +// self.imageView.frame = self.destinationImageFrame(for: webViewFrame.size, +// preview: preview) + self.imageView.frame = mainViewController.viewCoordinator.contentContainer.frame self.imageView.alpha = 1 self.solidBackground.alpha = 1 From 82a6db217887d8d1e506968be7bda2d7e3418f7e Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Thu, 11 Jan 2024 17:08:46 +0000 Subject: [PATCH 06/16] correct grab tab preview --- .../xcshareddata/xcschemes/DuckDuckGo.xcscheme | 2 +- DuckDuckGo/BrowserChromeManager.swift | 4 ---- DuckDuckGo/MainViewController.swift | 17 +++++++---------- DuckDuckGo/TabViewController.swift | 7 +++++-- DuckDuckGo/WebViewTransition.swift | 9 +++++---- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo.xcscheme b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo.xcscheme index 7c553f4089..e564636928 100644 --- a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo.xcscheme +++ b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> diff --git a/DuckDuckGo/BrowserChromeManager.swift b/DuckDuckGo/BrowserChromeManager.swift index baa9f557cf..3f458dd74f 100644 --- a/DuckDuckGo/BrowserChromeManager.swift +++ b/DuckDuckGo/BrowserChromeManager.swift @@ -72,10 +72,6 @@ class BrowserChromeManager: NSObject, UIScrollViewDelegate { observation = nil } - func scrollViewDidChangeAdjustedContentInset(_ scrollView: UIScrollView) { - print(#function) - } - private func scrollViewDidResizeContent(_ scrollView: UIScrollView) { if !canHideBars(for: scrollView) && animator.barsState != .revealed { animator.revealBars(animated: true) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 45ad4ab430..c11f4effaa 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -1334,19 +1334,16 @@ extension MainViewController: BrowserChromeDelegate { } func completion(_ finished: Bool) { + let top: CGFloat = viewCoordinator.statusBackground.frame.height * percent + let bottom: CGFloat if self.appSettings.currentAddressBarPosition == .top { - let top: CGFloat = self.viewCoordinator.statusBackground.frame.height * percent - let bottom: CGFloat = (self.viewCoordinator.toolbar.frame.height * percent) - + self.view.safeAreaInsets.bottom + self.additionalSafeAreaInsets.bottom - print("***", bottom, top, percent, animated) - self.currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + bottom = (viewCoordinator.toolbar.frame.height * percent) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom } else { - let top: CGFloat = self.viewCoordinator.statusBackground.frame.height * percent - let bottom: CGFloat = ((self.viewCoordinator.toolbar.frame.height + self.viewCoordinator.navigationBarContainer.frame.height) * percent) - + self.view.safeAreaInsets.bottom + self.additionalSafeAreaInsets.bottom - print("***", bottom, top, percent, animated) - self.currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height) * percent) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom } + currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) } if animated { diff --git a/DuckDuckGo/TabViewController.swift b/DuckDuckGo/TabViewController.swift index 2a970476fc..81c0f4c713 100644 --- a/DuckDuckGo/TabViewController.swift +++ b/DuckDuckGo/TabViewController.swift @@ -1145,9 +1145,12 @@ extension TabViewController: WKNavigationDelegate { func preparePreview(completion: @escaping (UIImage?) -> Void) { DispatchQueue.main.async { [weak self] in - guard let webView = self?.webView, + guard let main = self?.parent as? MainViewController, + let webView = self?.webView, webView.bounds.height > 0 && webView.bounds.width > 0 else { completion(nil); return } - UIGraphicsBeginImageContextWithOptions(webView.bounds.size, false, UIScreen.main.scale) + + UIGraphicsBeginImageContextWithOptions(main.viewCoordinator.contentContainer.frame.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, diff --git a/DuckDuckGo/WebViewTransition.swift b/DuckDuckGo/WebViewTransition.swift index 9167c270b1..af7ffbc8fe 100644 --- a/DuckDuckGo/WebViewTransition.swift +++ b/DuckDuckGo/WebViewTransition.swift @@ -90,7 +90,7 @@ class FromWebViewTransition: WebViewTransition { solidBackground.backgroundColor = theme.backgroundColor solidBackground.frame = webViewFrame - imageContainer.frame = webViewFrame + imageContainer.frame = mainViewController.viewCoordinator.contentContainer.frame imageView.frame = imageContainer.bounds imageView.image = preview @@ -165,11 +165,12 @@ class ToWebViewTransition: WebViewTransition { scrollIfOutsideViewport(collectionView: tabSwitcherViewController.collectionView, rowIndex: rowIndex, attributes: layoutAttr) UIView.animate(withDuration: TabSwitcherTransition.Constants.duration, animations: { + let frame = CGRect(x: 0, y: webView.scrollView.contentInset.top, width: webViewFrame.width, height: webViewFrame.height) self.imageContainer.frame = mainViewController.viewCoordinator.contentContainer.frame self.imageContainer.layer.cornerRadius = 0 -// self.imageView.frame = self.destinationImageFrame(for: webViewFrame.size, -// preview: preview) - self.imageView.frame = mainViewController.viewCoordinator.contentContainer.frame + + self.imageView.frame = self.destinationImageFrame(for: webViewFrame.size, + preview: preview) self.imageView.alpha = 1 self.solidBackground.alpha = 1 From f88f0f3273c312524690230ad333400cccb075d8 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 10:14:38 +0000 Subject: [PATCH 07/16] remove unused constant --- DuckDuckGo/BrowserChromeManager.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/DuckDuckGo/BrowserChromeManager.swift b/DuckDuckGo/BrowserChromeManager.swift index 3f458dd74f..c59afa3bd0 100644 --- a/DuckDuckGo/BrowserChromeManager.swift +++ b/DuckDuckGo/BrowserChromeManager.swift @@ -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" From 41f3197323857a028de0c8c1c52bd4652f7603fd Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 10:15:01 +0000 Subject: [PATCH 08/16] refresh the insets when something changes in the ui --- DuckDuckGo/MainViewController.swift | 37 ++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index c11f4effaa..17919dcb39 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -1332,28 +1332,32 @@ extension MainViewController: BrowserChromeDelegate { self.viewCoordinator.tabBarContainer.alpha = percent self.viewCoordinator.toolbar.alpha = percent } - - func completion(_ finished: Bool) { - let top: CGFloat = viewCoordinator.statusBackground.frame.height * percent - let bottom: CGFloat - if self.appSettings.currentAddressBarPosition == .top { - bottom = (viewCoordinator.toolbar.frame.height * percent) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom - } else { - bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height) * percent) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom - } - currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) - } - + if animated { - UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock, completion: completion) + UIView.animate(withDuration: ChromeAnimationConstants.duration, animations: updateBlock) { _ in + self.refreshWebViewContentInsets() + } } else { updateBlock() - completion(true) + self.refreshWebViewContentInsets() } } + func refreshWebViewContentInsets() { + guard let webView = currentTab?.webView else { return } + + let top: CGFloat = viewCoordinator.statusBackground.frame.height + let bottom: CGFloat + if self.appSettings.currentAddressBarPosition == .top { + bottom = (viewCoordinator.toolbar.frame.height) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + } else { + bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height)) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + } + currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + } + func setNavigationBarHidden(_ hidden: Bool) { if hidden { hideKeyboard() } @@ -1823,6 +1827,7 @@ extension MainViewController: TabDelegate { func showBars() { chromeManager.reset() + refreshWebViewContentInsets() } func tabDidRequestFindInPage(tab: TabViewController) { From 0bf4dd56e3dfa97ff68ae342dfae7ade98a551a9 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 10:32:20 +0000 Subject: [PATCH 09/16] fix scrolling problem --- DuckDuckGo/BarsAnimator.swift | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/DuckDuckGo/BarsAnimator.swift b/DuckDuckGo/BarsAnimator.swift index d2f4a8d758..01cae59724 100644 --- a/DuckDuckGo/BarsAnimator.swift +++ b/DuckDuckGo/BarsAnimator.swift @@ -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) { @@ -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) { @@ -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) { From c692cfe149c766074afe75f31ba17d35218eac14 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 10:41:23 +0000 Subject: [PATCH 10/16] set inset correctly for bar positions --- DuckDuckGo/MainViewController.swift | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 17919dcb39..abcfd8aff0 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -430,6 +430,7 @@ class MainViewController: UIViewController { @objc func onAddressBarPositionChanged() { viewCoordinator.moveAddressBarToPosition(appSettings.currentAddressBarPosition) refreshViewsBasedOnAddressBarPosition(appSettings.currentAddressBarPosition) + refreshWebViewContentInsets() } func refreshViewsBasedOnAddressBarPosition(_ position: AddressBarPosition) { @@ -1346,15 +1347,24 @@ extension MainViewController: BrowserChromeDelegate { func refreshWebViewContentInsets() { guard let webView = currentTab?.webView else { return } - let top: CGFloat = viewCoordinator.statusBackground.frame.height + let top: CGFloat let bottom: CGFloat - if self.appSettings.currentAddressBarPosition == .top { - bottom = (viewCoordinator.toolbar.frame.height) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + if isToolbarHidden { + + top = 0.0 + bottom = 0.0 + } else { - bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height)) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + top = viewCoordinator.statusBackground.frame.height + if self.appSettings.currentAddressBarPosition == .top { + bottom = (viewCoordinator.toolbar.frame.height) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + } else { + bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height)) + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + } } + currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) } From 657b50a875cf73b6f2671aef93311ce487dd13a5 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 12:04:53 +0000 Subject: [PATCH 11/16] build keyboard frame into content inset calculation --- DuckDuckGo/MainViewController.swift | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index abcfd8aff0..01cd2c6f2f 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -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:") @@ -476,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) @@ -1347,22 +1350,19 @@ extension MainViewController: BrowserChromeDelegate { func refreshWebViewContentInsets() { guard let webView = currentTab?.webView else { return } - let top: CGFloat + let top = viewCoordinator.statusBackground.frame.height let bottom: CGFloat if isToolbarHidden { - - top = 0.0 - bottom = 0.0 - + bottom = 0 + } else if appSettings.currentAddressBarPosition.isBottom { + bottom = viewCoordinator.toolbar.frame.height + + viewCoordinator.navigationBarContainer.frame.height + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + + keyboardHeight } else { - top = viewCoordinator.statusBackground.frame.height - if self.appSettings.currentAddressBarPosition == .top { - bottom = (viewCoordinator.toolbar.frame.height) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom - } else { - bottom = ((viewCoordinator.toolbar.frame.height + viewCoordinator.navigationBarContainer.frame.height)) - + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom - } + bottom = viewCoordinator.toolbar.frame.height + + view.safeAreaInsets.bottom + additionalSafeAreaInsets.bottom + + keyboardHeight } currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) From 9e68c9e3fb7806f3f8e9fb785171c0f68b333915 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 12:27:25 +0000 Subject: [PATCH 12/16] use a dedicated container view in the coordinator --- DuckDuckGo/MainView.swift | 33 +++++++++++++++++++++++------ DuckDuckGo/MainViewController.swift | 21 +++++++++--------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/DuckDuckGo/MainView.swift b/DuckDuckGo/MainView.swift index e78b925d59..d998f53826 100644 --- a/DuckDuckGo/MainView.swift +++ b/DuckDuckGo/MainView.swift @@ -54,6 +54,7 @@ class MainViewFactory { extension MainViewFactory { private func createViews() { + createWebViewContainer() createLogoBackground() createContentContainer() createSuggestionTrayContainer() @@ -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 @@ -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 @@ -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")) @@ -156,6 +163,7 @@ extension MainViewFactory { extension MainViewFactory { private func constrainViews() { + constrainWebViewContainer() constrainLogoBackground() constrainContentContainer() constrainSuggestionTrayContainer() @@ -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! @@ -333,6 +351,7 @@ class MainViewCoordinator { var toolbarFireButton: UIBarButtonItem! var toolbarForwardButton: UIBarButtonItem! var toolbarTabSwitcherButton: UIBarButtonItem! + var webViewContainer: UIView! let constraints = Constraints() diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 01cd2c6f2f..793c9d5de3 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -644,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() @@ -704,7 +704,7 @@ class MainViewController: UIViewController { controller.chromeDelegate = self controller.delegate = self - addToView(controller: controller) + addToContentContainer(controller: controller) refreshControls() syncService.scheduler.requestSyncImmediately() @@ -853,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) { @@ -867,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) @@ -876,17 +876,16 @@ class MainViewController: UIViewController { } } - private func addToView(tab: TabViewController) { + private func addToWebViewContainer(tab: TabViewController) { removeHomeScreen() updateFindInPage() currentTab?.progressWorker.progressBar = nil currentTab?.chromeDelegate = nil currentTab?.webView.scrollView.contentInsetAdjustmentBehavior = .never - - // addToView(controller: tab) + addChild(tab) - tab.willMove(toParent: self) - view.insertSubview(tab.view, at: 0) + viewCoordinator.webViewContainer.subviews.forEach { $0.removeFromSuperview() } + viewCoordinator.webViewContainer.addSubview(tab.view) tab.view.frame = self.view.frame tab.didMove(toParent: self) @@ -898,7 +897,7 @@ class MainViewController: UIViewController { 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() } @@ -1733,7 +1732,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() } From 6e5d9782429c87063d20d83c7fb76e6379c26723 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 14:14:36 +0000 Subject: [PATCH 13/16] use guideview not parent --- DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift b/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift index 9752a564c1..867f7cc79a 100644 --- a/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift +++ b/DuckDuckGo/BrowsingMenu/BrowsingMenuViewController.swift @@ -157,7 +157,7 @@ final class BrowsingMenuViewController: UIViewController { recalculatePreferredWidthConstraint() recalculateHeightConstraints() - parent?.view.map(recalculateMenuConstraints(with:)) + guideView.map(recalculateMenuConstraints(with:)) if tableView.bounds.height < tableView.contentSize.height + tableView.contentInset.top + tableView.contentInset.bottom { tableView.isScrollEnabled = true From 4c532350b8bdbf47b3baa8616d2bd3ee82d557aa Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 14:17:45 +0000 Subject: [PATCH 14/16] use nonoptional var --- DuckDuckGo/MainViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index 793c9d5de3..bd2d8ebe1f 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -1364,7 +1364,7 @@ extension MainViewController: BrowserChromeDelegate { + keyboardHeight } - currentTab?.webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) + webView.scrollView.contentInset = .init(top: top, left: 0, bottom: bottom, right: 0) } func setNavigationBarHidden(_ hidden: Bool) { From 115b04011baf8c3e1ec4e3b05f628d70518ce279 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 14:32:42 +0000 Subject: [PATCH 15/16] calculate preview size without needing main view controller --- DuckDuckGo/TabViewController.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/DuckDuckGo/TabViewController.swift b/DuckDuckGo/TabViewController.swift index 81c0f4c713..22593be12e 100644 --- a/DuckDuckGo/TabViewController.swift +++ b/DuckDuckGo/TabViewController.swift @@ -1145,11 +1145,13 @@ extension TabViewController: WKNavigationDelegate { func preparePreview(completion: @escaping (UIImage?) -> Void) { DispatchQueue.main.async { [weak self] in - guard let main = self?.parent as? MainViewController, - let webView = self?.webView, + guard let webView = self?.webView, webView.bounds.height > 0 && webView.bounds.width > 0 else { completion(nil); return } - UIGraphicsBeginImageContextWithOptions(main.viewCoordinator.contentContainer.frame.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 { From c10dd4e0d3f28a7dfa2f3639796414de971020c8 Mon Sep 17 00:00:00 2001 From: Chris Brind Date: Fri, 12 Jan 2024 14:47:46 +0000 Subject: [PATCH 16/16] fix bug when restarting where view would be too big --- DuckDuckGo/MainViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index bd2d8ebe1f..920c674066 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -886,7 +886,7 @@ class MainViewController: UIViewController { addChild(tab) viewCoordinator.webViewContainer.subviews.forEach { $0.removeFromSuperview() } viewCoordinator.webViewContainer.addSubview(tab.view) - tab.view.frame = self.view.frame + tab.view.frame = self.viewCoordinator.webViewContainer.bounds tab.didMove(toParent: self) viewCoordinator.logoContainer.isHidden = true