Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Home Page Picker] Update the design of the “Choose a Domain” screen #15324

Merged
merged 41 commits into from
Nov 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
9f7d0de
Add Analytic events for site design selection
chipsnyder Nov 6, 2020
959393b
Update Podspec for WordPressShared beta branch
chipsnyder Nov 6, 2020
edf1782
Add Analytic events for site design selection
chipsnyder Nov 6, 2020
781e5a1
Update Podspec for WordPressShared beta branch
chipsnyder Nov 6, 2020
d174253
Adds image retry logic if the requested url didn't match the result
chipsnyder Nov 6, 2020
16fe5af
Throttle the retry requests to make sure we're not polling too quickly
chipsnyder Nov 6, 2020
de71ca1
Add Preview button
chipsnyder Nov 11, 2020
bba85f5
Move Visibility helper to WordPressUI
chipsnyder Nov 11, 2020
db6b791
Add Preview View Controller
chipsnyder Nov 11, 2020
ff5e5b2
Update constraints for ghostview
chipsnyder Nov 11, 2020
6385807
Update Podfile to reference branch
chipsnyder Nov 11, 2020
271b2e7
Fix issue where scrollable area was off by 1
chipsnyder Nov 12, 2020
269c7b3
Connect Choose button
chipsnyder Nov 12, 2020
d0bc2a0
Handle Errors and add show progress bar for loading
chipsnyder Nov 12, 2020
d754a4e
Add analytics
chipsnyder Nov 12, 2020
1161b4c
Update Presentation to be pagesheet to match designs
chipsnyder Nov 13, 2020
9f38677
Merge branch 'develop' into gutenberg/hpp/2720-preview
chipsnyder Nov 16, 2020
96e51ca
Add new content view controller for domain selection
chipsnyder Nov 16, 2020
8fb23fe
Extract Filterbar to be a replaceable accessory view
chipsnyder Nov 16, 2020
11230e8
Convert Domain View controller to use collapsable header view
chipsnyder Nov 17, 2020
f29527d
Add additional separator style
chipsnyder Nov 17, 2020
d1bced6
Fix cell border issue
chipsnyder Nov 17, 2020
f823302
Manage scrollable space when suggestions load
chipsnyder Nov 17, 2020
661fe82
Remove replaced files
chipsnyder Nov 17, 2020
234b703
Add the network error cell
chipsnyder Nov 18, 2020
be07eca
Add error tracking
chipsnyder Nov 18, 2020
8c801b8
Fix Estimated content size when the screen is NOT showing an error
chipsnyder Nov 18, 2020
67b79b1
Add punctuation
chipsnyder Nov 18, 2020
ff47866
Remove unused code
chipsnyder Nov 18, 2020
67f49d1
Clean up some repeated code
chipsnyder Nov 18, 2020
a9337dd
Adjust some formatting
chipsnyder Nov 18, 2020
2630563
Hide small header when big scroll jumps happen
chipsnyder Nov 18, 2020
12aa54b
Merge branch 'develop' into gutenberg/hpp/2722-DomainUI
chipsnyder Nov 19, 2020
0a6b89b
Increase top padding on CollapsableHeaderView
chipsnyder Nov 19, 2020
ce7375c
Maintain scroll offset if destroyed by the system
chipsnyder Nov 19, 2020
20640b1
Tweak estimated cell size to better fit screen
chipsnyder Nov 19, 2020
aa2bc56
Merge branch 'develop' into gutenberg/hpp/2720-preview
chipsnyder Nov 19, 2020
2ee993f
Merge branch 'gutenberg/hpp/2720-preview' into gutenberg/hpp/2722-Dom…
chipsnyder Nov 19, 2020
bf2897e
Update Podfile for beta version of WordPressUI
chipsnyder Nov 19, 2020
0506541
Merge branch 'gutenberg/hpp/2720-preview' into gutenberg/hpp/2722-Dom…
chipsnyder Nov 19, 2020
3afe24b
Merge branch 'develop'
chipsnyder Nov 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,36 @@ class CollapsableHeaderFilterBar: UICollectionView {
var filterDelegate: CollapsableHeaderFilterBarDelegate?
private let defaultCellHeight: CGFloat = 44
private let defaultCellWidth: CGFloat = 105

var shouldShowGhostContent: Bool = false {
didSet {
reloadData()
}
}

init() {
let collectionViewLayout = UICollectionViewFlowLayout()
collectionViewLayout.sectionInset = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
collectionViewLayout.minimumInteritemSpacing = 12
collectionViewLayout.minimumLineSpacing = 10
collectionViewLayout.scrollDirection = .horizontal
super.init(frame: .zero, collectionViewLayout: collectionViewLayout)
showsHorizontalScrollIndicator = false
showsVerticalScrollIndicator = false
commonInit()
}

required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}

private func commonInit() {
register(CollabsableHeaderFilterCollectionViewCell.nib, forCellWithReuseIdentifier: CollabsableHeaderFilterCollectionViewCell.cellReuseIdentifier)
self.delegate = self
self.dataSource = self
self.backgroundColor = .clear
self.isOpaque = false
}

private func deselectItem(_ indexPath: IndexPath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,25 @@ import WordPressUI
class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
enum SeperatorStyle {
case visibile
case automatic
case hidden
}

let scrollableView: UIScrollView
let accessoryView: UIView?
let mainTitle: String
let prompt: String
let primaryActionTitle: String
let secondaryActionTitle: String?
let defaultActionTitle: String?
private let seperatorStyle: SeperatorStyle
open var accessoryBarHeight: CGFloat {
return 44
}

open var seperatorStyle: SeperatorStyle {
return self.hasAccessoryBar ? .visibile : .automatic
}

private let hasDefaultAction: Bool

@IBOutlet weak var containerView: UIView!
Expand All @@ -25,10 +34,11 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
title.isHidden = true
return title
}()
@IBOutlet weak var largeTitleTopSpacingConstraint: NSLayoutConstraint!
@IBOutlet weak var largeTitleView: UILabel!
@IBOutlet weak var promptView: UILabel!
@IBOutlet weak var filterBar: CollapsableHeaderFilterBar!
@IBOutlet weak var filterBarHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var accessoryBar: UIView!
@IBOutlet weak var accessoryBarHeightConstraint: NSLayoutConstraint!
@IBOutlet weak var footerView: UIView!
@IBOutlet weak var footerHeightContraint: NSLayoutConstraint!
@IBOutlet weak var defaultActionButton: UIButton!
Expand Down Expand Up @@ -71,9 +81,9 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
}
}

private let hasFilterBar: Bool
private var shouldHideFilterBar: Bool {
return isShowingNoResults || !hasFilterBar
private let hasAccessoryBar: Bool
private var shouldHideAccessoryBar: Bool {
return isShowingNoResults || !hasAccessoryBar
}

private var shouldUseCompactLayout: Bool {
Expand Down Expand Up @@ -149,24 +159,24 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
/// - primaryActionTitle: The button title for the right most button when an item is selected. Required.
/// - secondaryActionTitle: The button title for the left most button when an item is selected. Optional - nil results in the left most button being hidden when an item is selected.
/// - defaultActionTitle: The button title for the button that is displayed when no item is selected. Optional - nil results in the footer being hidden when no item is selected.
/// - hasFilterBar: Determines if the filter bar should be shown or not. Optional - The default is shown.
/// - accessoryView: The view to be placed in the placeholder of the accessory bar. Optional - The default is nil.
///
init(scrollableView: UIScrollView,
mainTitle: String,
prompt: String,
primaryActionTitle: String,
secondaryActionTitle: String? = nil,
defaultActionTitle: String? = nil,
hasFilterBar: Bool = true) {
accessoryView: UIView? = nil) {
self.scrollableView = scrollableView
self.mainTitle = mainTitle
self.prompt = prompt
self.primaryActionTitle = primaryActionTitle
self.secondaryActionTitle = secondaryActionTitle
self.defaultActionTitle = defaultActionTitle
self.hasFilterBar = hasFilterBar
self.hasAccessoryBar = (accessoryView != nil)
self.hasDefaultAction = (defaultActionTitle != nil)
self.seperatorStyle = hasFilterBar ? .visibile : .hidden
self.accessoryView = accessoryView
super.init(nibName: "\(CollapsableHeaderViewController.self)", bundle: .main)
}

Expand All @@ -177,6 +187,7 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
override func viewDidLoad() {
super.viewDidLoad()
insertChildView()
insertAccessoryView()
navigationItem.titleView = titleView
largeTitleView.font = WPStyleGuide.serifFontForTextStyle(UIFont.TextStyle.largeTitle, fontWeight: .semibold)
toggleFilterBarConstraints()
Expand All @@ -191,6 +202,7 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
formatNavigationController()
extendedLayoutIncludesOpaqueBars = true
edgesForExtendedLayout = .top
updateSeperatorStyle()
}

/// The estimated content size of the scroll view. This is used to adjust the content insests to allow the header to be scrollable to be collapsable still when
Expand Down Expand Up @@ -230,7 +242,7 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
guard isShowingNoResults else { return }
coordinator.animate { (_) in
self.updateHeaderDisplay()
if self.shouldHideFilterBar {
if self.shouldHideAccessoryBar {
self.disableInitialLayoutHelpers()
self.snapToHeight(self.scrollableView, height: self.minHeaderHeight, animated: false)
}
Expand Down Expand Up @@ -355,6 +367,17 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
containerView.addConstraints([top, bottom, leading, trailing])
}

private func insertAccessoryView() {
guard let accessoryView = accessoryView else { return }
accessoryView.translatesAutoresizingMaskIntoConstraints = false
let top = NSLayoutConstraint(item: accessoryView, attribute: .top, relatedBy: .equal, toItem: accessoryBar, attribute: .top, multiplier: 1, constant: 0)
let bottom = NSLayoutConstraint(item: accessoryView, attribute: .bottom, relatedBy: .equal, toItem: accessoryBar, attribute: .bottom, multiplier: 1, constant: 0)
let leading = NSLayoutConstraint(item: accessoryView, attribute: .leading, relatedBy: .equal, toItem: accessoryBar, attribute: .leading, multiplier: 1, constant: 0)
let trailing = NSLayoutConstraint(item: accessoryView, attribute: .trailing, relatedBy: .equal, toItem: accessoryBar, attribute: .trailing, multiplier: 1, constant: 0)
accessoryBar.addSubview(accessoryView)
accessoryBar.addConstraints([top, bottom, leading, trailing])
}

private func styleButtons() {
let seperator: UIColor
if #available(iOS 13.0, *) {
Expand All @@ -377,31 +400,33 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {

// MARK: - Header and Footer Sizing
private func toggleFilterBarConstraints() {
filterBarHeightConstraint.constant = shouldHideFilterBar ? 0 : 44
maxHeaderBottomSpacing.constant = shouldHideFilterBar ? 1 : 24
minHeaderBottomSpacing.constant = shouldHideFilterBar ? 1 : 9
accessoryBarHeightConstraint.constant = shouldHideAccessoryBar ? 0 : accessoryBarHeight
let collapseBottomSpacing = shouldHideAccessoryBar || (seperatorStyle == .hidden)
maxHeaderBottomSpacing.constant = collapseBottomSpacing ? 1 : 24
minHeaderBottomSpacing.constant = collapseBottomSpacing ? 1 : 9
}

private func updateHeaderDisplay() {
headerHeightConstraint.isActive = false
initialHeaderTopConstraint.isActive = true
toggleFilterBarConstraints()
filterBar.layoutIfNeeded()
accessoryBar.layoutIfNeeded()
headerView.layoutIfNeeded()
calculateHeaderSnapPoints()
layoutHeaderInsets()
}

private func calculateHeaderSnapPoints() {
if shouldHideFilterBar {
let accessoryBarSpacing: CGFloat
if shouldHideAccessoryBar {
minHeaderHeight = 1
_midHeaderHeight = titleToSubtitleSpacing.constant + promptView.frame.height + subtitleToCategoryBarSpacing.constant + minHeaderHeight
_maxHeaderHeight = largeTitleView.frame.height + _midHeaderHeight
accessoryBarSpacing = minHeaderHeight
} else {
minHeaderHeight = filterBarHeightConstraint.constant + minHeaderBottomSpacing.constant
_midHeaderHeight = titleToSubtitleSpacing.constant + promptView.frame.height + subtitleToCategoryBarSpacing.constant + filterBarHeightConstraint.constant + maxHeaderBottomSpacing.constant
_maxHeaderHeight = largeTitleView.frame.height + _midHeaderHeight
minHeaderHeight = accessoryBarHeightConstraint.constant + minHeaderBottomSpacing.constant
accessoryBarSpacing = accessoryBarHeightConstraint.constant + maxHeaderBottomSpacing.constant
}
_midHeaderHeight = titleToSubtitleSpacing.constant + promptView.frame.height + subtitleToCategoryBarSpacing.constant + accessoryBarSpacing
_maxHeaderHeight = largeTitleTopSpacingConstraint.constant + largeTitleView.frame.height + _midHeaderHeight
}

private func layoutHeaderInsets() {
Expand Down Expand Up @@ -474,9 +499,14 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
hideNoResults()
}

/// In scenarios where the content offset before content changes doesn't align with the available space after the content changes then the offset can be lost. In
/// order to preserve the header's collpased state we cache the offset and attempt to reapply it if needed.
private var stashedOffset: CGPoint? = nil

/// A public interface to notify the container that the content size of the scroll view is about to change. This is useful in adjusting the bottom insets to allow the
/// view to still be scrollable with the content size is less than the total space of the expanded screen.
public func contentSizeWillChange() {
stashedOffset = scrollableView.contentOffset
updateFooterInsets()
}

Expand Down Expand Up @@ -510,21 +540,16 @@ class CollapsableHeaderViewController: UIViewController, NoResultsViewHost {
}
}

/// A public interface to notify the container that the content view is loading content still
public func loadingStateChanged(_ isLoading: Bool) {
filterBar.shouldShowGhostContent = isLoading
filterBar.allowsMultipleSelection = !isLoading
filterBar.reloadData()
}

// MARK: - Seperator styling
private func updateSeperatorStyle(animated: Bool = true) {
let shouldBeHidden: Bool
switch seperatorStyle {
case .hidden:
case .automatic:
shouldBeHidden = seperator.frame.minY > minHeaderHeight
case .visibile:
shouldBeHidden = false
case .hidden:
shouldBeHidden = true
}

seperator.animatableSetIsHidden(shouldBeHidden, animated: animated)
Expand All @@ -541,14 +566,21 @@ extension CollapsableHeaderViewController: UIScrollViewDelegate {
}
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard !shouldUseCompactLayout,
!isShowingNoResults else {
titleView.animatableSetIsHidden(false, animated: true)
return
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
/// Clear the stashed offset because the user has initiated a change
stashedOffset = nil
}

/// Restores the stashed content offset if it appears as if it's been reset.
private func restorContentOffsetIfNeeded(_ scrollView: UIScrollView) {
guard let stashedOffset = stashedOffset else { return }
if scrollView.contentOffset.y == 0 { // Offset has probably been reset
scrollView.contentOffset = stashedOffset
}
disableInitialLayoutHelpers()
self.stashedOffset = nil
}

private func resizeHeaderIfNeeded(_ scrollView: UIScrollView) {
let scrollOffset = scrollView.contentOffset.y + topInset
let newHeaderViewHeight = maxHeaderHeight - scrollOffset

Expand All @@ -557,9 +589,24 @@ extension CollapsableHeaderViewController: UIScrollViewDelegate {
} else {
headerHeightConstraint.constant = newHeaderViewHeight
}
}

fileprivate func updateTitleViewVisibility(_ animated: Bool = true) {
let shouldHide = (headerHeightConstraint.constant > midHeaderHeight) && !shouldUseCompactLayout
titleView.animatableSetIsHidden(shouldHide, animated: animated)
}

func scrollViewDidScroll(_ scrollView: UIScrollView) {
restorContentOffsetIfNeeded(scrollView)

let shouldHide = (largeTitleView.frame.maxY > 0)
titleView.animatableSetIsHidden(shouldHide, animated: true)
guard !shouldUseCompactLayout,
!isShowingNoResults else {
updateTitleViewVisibility(true)
return
}
disableInitialLayoutHelpers()
resizeHeaderIfNeeded(scrollView)
updateTitleViewVisibility()
updateSeperatorStyle()
}

Expand Down Expand Up @@ -588,16 +635,14 @@ extension CollapsableHeaderViewController: UIScrollViewDelegate {
private func snapToHeight(_ scrollView: UIScrollView, height: CGFloat, animated: Bool = true) {
scrollView.contentOffset.y = maxHeaderHeight - height - topInset
headerHeightConstraint.constant = height
let shouldHide = (height >= maxHeaderHeight) && !shouldUseCompactLayout
titleView.animatableSetIsHidden(shouldHide, animated: animated)
updateTitleViewVisibility(animated)
updateSeperatorStyle(animated: animated)

guard animated else {
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
updateSeperatorStyle()
return
}
updateSeperatorStyle()
UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: .curveEaseInOut, animations: {
self.headerView.setNeedsLayout()
self.headerView.layoutIfNeeded()
Expand Down
Loading