Skip to content

Commit

Permalink
Animate transition between New Tab Page and tab switcher (#3196)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/72649045549333/1207977496450583/f
Tech Design URL:
CC:

**Description**:

Adopts tab switcher transition to New Tab Page. I took a chance to clean
up the old "centered search" feature, which made the adoption a bit
easier.

**Steps to test this PR**:
1. Check transitions of Home screen to/from tab switcher with and
without favorites
2. Enable New Tab Page sections in Debug menu
3. Check transitions of New Tab Page to/from tab switcher with sections
visible and turned off (Dax logo visible)
4. Create new tab from switcher. The NTP should scale up and fade in.
  • Loading branch information
dus7 authored Aug 7, 2024
1 parent 3ea8fd3 commit 45220c5
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 160 deletions.
13 changes: 8 additions & 5 deletions DuckDuckGo/Assets.xcassets/Home.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "home.pdf"
"filename" : "home.pdf",
"idiom" : "universal"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
}
125 changes: 3 additions & 122 deletions DuckDuckGo/Base.lproj/Home.storyboard

Large diffs are not rendered by default.

36 changes: 13 additions & 23 deletions DuckDuckGo/HomeScreenTransition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,30 @@

import Core

protocol HomeScreenTransitionSource: AnyObject {
var snapshotView: UIView { get }
var rootContainerView: UIView { get }
}

class HomeScreenTransition: TabSwitcherTransition {

fileprivate var homeScreenSnapshot: UIView?
fileprivate var settingsButtonSnapshot: UIView?

fileprivate let tabSwitcherSettings: TabSwitcherSettings = DefaultTabSwitcherSettings()

fileprivate func prepareSnapshots(with homeScreen: HomeViewController,
fileprivate func prepareSnapshots(with transitionSource: HomeScreenTransitionSource,
transitionContext: UIViewControllerContextTransitioning) {
let viewToSnapshot: UIView
let frameToSnapshot: CGRect
if let logoContainer = homeScreen.logoContainer, !logoContainer.isHidden {
viewToSnapshot = logoContainer
frameToSnapshot = homeScreen.collectionView.convert(homeScreen.collectionView.bounds,
to: nil)
} else {
viewToSnapshot = homeScreen.collectionView
frameToSnapshot = viewToSnapshot.bounds
}

let viewToSnapshot = transitionSource.snapshotView
let frameToSnapshot = transitionSource.rootContainerView.convert(transitionSource.rootContainerView.bounds, to: viewToSnapshot)

if let snapshot = viewToSnapshot.resizableSnapshotView(from: frameToSnapshot,
afterScreenUpdates: false,
withCapInsets: .zero) {
imageContainer.addSubview(snapshot)
snapshot.frame = imageContainer.bounds
homeScreenSnapshot = snapshot
}

// This fixes animation glitch in centered search mode.
settingsButtonSnapshot = homeScreen.settingsButton.snapshotView(afterScreenUpdates: true)
if let settingsButton = settingsButtonSnapshot {
settingsButton.frame = homeScreen.view.convert(homeScreen.settingsButton.frame, to: nil)
transitionContext.containerView.addSubview(settingsButton)
}
}

fileprivate func tabSwitcherCellFrame(for attributes: UICollectionViewLayoutAttributes) -> CGRect {
Expand Down Expand Up @@ -100,7 +90,7 @@ class FromHomeScreenTransition: HomeScreenTransition {
tabSwitcherViewController.view.frame = transitionContext.finalFrame(for: tabSwitcherViewController)
tabSwitcherViewController.prepareForPresentation()

guard let homeScreen = mainViewController.homeViewController,
guard let homeScreen = mainViewController.homeController,
let tab = mainViewController.tabManager.model.currentTab,
let rowIndex = tabSwitcherViewController.tabsModel.indexOf(tab: tab),
let layoutAttr = tabSwitcherViewController.collectionView.layoutAttributesForItem(at: IndexPath(row: rowIndex, section: 0))
Expand All @@ -112,7 +102,7 @@ class FromHomeScreenTransition: HomeScreenTransition {

let theme = ThemeManager.shared.currentTheme

solidBackground.frame = homeScreen.view.convert(homeScreen.collectionView.frame, to: nil)
solidBackground.frame = homeScreen.view.convert(homeScreen.rootContainerView.frame, to: nil)
solidBackground.backgroundColor = theme.backgroundColor

imageContainer.frame = solidBackground.frame
Expand Down Expand Up @@ -173,7 +163,7 @@ class ToHomeScreenTransition: HomeScreenTransition {
prepareSubviews(using: transitionContext)

guard let mainViewController = transitionContext.viewController(forKey: .to) as? MainViewController,
let homeScreen = mainViewController.homeViewController,
let homeScreen = mainViewController.homeController,
let tab = mainViewController.tabManager.model.currentTab,
let rowIndex = tabSwitcherViewController.tabsModel.indexOf(tab: tab),
let layoutAttr = tabSwitcherViewController.collectionView.layoutAttributesForItem(at: IndexPath(row: rowIndex, section: 0))
Expand Down Expand Up @@ -206,7 +196,7 @@ class ToHomeScreenTransition: HomeScreenTransition {
UIView.animateKeyframes(withDuration: TabSwitcherTransition.Constants.duration, delay: 0, options: .calculationModeLinear, animations: {

UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 1.0) {
self.imageContainer.frame = homeScreen.view.convert(homeScreen.collectionView.frame, to: nil)
self.imageContainer.frame = homeScreen.view.convert(homeScreen.rootContainerView.frame, to: nil)
self.imageContainer.layer.cornerRadius = 0
self.imageContainer.backgroundColor = theme.backgroundColor
self.imageView.frame = CGRect(origin: .zero,
Expand Down
16 changes: 10 additions & 6 deletions DuckDuckGo/HomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class HomeViewController: UIViewController, NewTabPage {
@IBOutlet weak var ctaContainer: UIView!

@IBOutlet weak var collectionView: HomeCollectionView!
@IBOutlet weak var settingsButton: UIButton!

@IBOutlet weak var daxDialogContainer: UIView!
@IBOutlet weak var daxDialogContainerHeight: NSLayoutConstraint!
Expand Down Expand Up @@ -149,7 +148,6 @@ class HomeViewController: UIViewController, NewTabPage {

collectionView.homePageConfiguration = homePageConfiguration
configureCollectionView()
decorate()

NotificationCenter.default.addObserver(self,
selector: #selector(remoteMessagesDidChange),
Expand Down Expand Up @@ -366,10 +364,16 @@ extension HomeViewController: HomeMessageViewSectionRendererDelegate {
}
}

extension HomeViewController {
extension HomeViewController: HomeScreenTransitionSource {
var snapshotView: UIView {
if let logoContainer = logoContainer, !logoContainer.isHidden {
return logoContainer
} else {
return collectionView
}
}

private func decorate() {
let theme = ThemeManager.shared.currentTheme
settingsButton.tintColor = theme.barTintColor
var rootContainerView: UIView {
collectionView
}
}
13 changes: 11 additions & 2 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class MainViewController: UIViewController {

var homeViewController: HomeViewController?
var newTabPageViewController: NewTabPageViewController?
var homeController: NewTabPage? {
var homeController: (NewTabPage & HomeScreenTransitionSource)? {
homeViewController ?? newTabPageViewController
}
var tabsBarController: TabsBarViewController?
Expand Down Expand Up @@ -2390,7 +2390,16 @@ extension MainViewController: TabSwitcherDelegate {

func tabSwitcherDidRequestNewTab(tabSwitcher: TabSwitcherViewController) {
newTab()
animateLogoAppearance()
if homeViewController != nil {
animateLogoAppearance()
} else if newTabPageViewController != nil {
newTabPageViewController?.view.transform = CGAffineTransform().scaledBy(x: 0.5, y: 0.5)
newTabPageViewController?.view.alpha = 0.0
UIView.animate(withDuration: 0.2, delay: 0.1, options: [.curveEaseInOut, .beginFromCurrentState]) {
self.newTabPageViewController?.view.transform = .identity
self.newTabPageViewController?.view.alpha = 1.0
}
}
}

func tabSwitcher(_ tabSwitcher: TabSwitcherViewController, didSelectTab tab: Tab) {
Expand Down
1 change: 0 additions & 1 deletion DuckDuckGo/NavigationSearchHomeViewSectionRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class NavigationSearchHomeViewSectionRenderer: HomeViewSectionRenderer {
controller.disableContentUnderflow()
controller.chromeDelegate?.setNavigationBarHidden(false)
controller.collectionView.isScrollEnabled = !fixed
controller.settingsButton.isHidden = true

if !fixed {
controller.hideLogo()
Expand Down
5 changes: 4 additions & 1 deletion DuckDuckGo/NewTabPageDaxLogoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ import SwiftUI

struct NewTabPageDaxLogoView: View {
var body: some View {
VStack {
VStack(spacing: 12) {
Image(.home)
.resizable()
.aspectRatio(1, contentMode: .fit)
.frame(width: 96)
Image(.textDuckDuckGo)
}
}
Expand Down
10 changes: 10 additions & 0 deletions DuckDuckGo/NewTabPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,13 @@ final class NewTabPageViewController: UIHostingController<NewTabPageView<Favorit
fatalError("init(coder:) has not been implemented")
}
}

extension NewTabPageViewController: HomeScreenTransitionSource {
var snapshotView: UIView {
view
}

var rootContainerView: UIView {
view
}
}

0 comments on commit 45220c5

Please sign in to comment.