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

[Site Design Revamp] Main View - remove filtering and action buttons #18506

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ class CollapsableHeaderCollectionViewCell: UICollectionViewCell {
}
}

/// Set to `true` to disable showing visual decorations like a checkmark or border when a cell is selected.
var selectionDecorationsHidden = false

override func prepareForReuse() {
super.prepareForReuse()
imageView.cancelImageDownload()
Expand Down Expand Up @@ -92,6 +95,12 @@ class CollapsableHeaderCollectionViewCell: UICollectionViewCell {
}

private func styleSelectedBorder(animated: Bool = false) {
guard !selectionDecorationsHidden else {
imageView.layer.borderColor = borderColor.cgColor
imageView.layer.borderWidth = borderWith
return
}

let imageBorderColor = isSelected ? accentColor.cgColor : borderColor.cgColor
let imageBorderWidth = isSelected ? 2 : borderWith
guard animated else {
Expand All @@ -117,6 +126,11 @@ class CollapsableHeaderCollectionViewCell: UICollectionViewCell {
}

private func checkmarkHidden(_ isHidden: Bool, animated: Bool = false) {
guard !selectionDecorationsHidden else {
checkmarkContainerView.isHidden = true
return
}

guard animated else {
checkmarkContainerView.isHidden = isHidden
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class CategorySectionTableViewCell: UITableViewCell {
}

var isGhostCell: Bool = false
/// Set to `true` to disable showing visual decorations like a checkmark or border when a cell is selected.
var selectionDecorationsHidden = false

override func prepareForReuse() {
section?.scrollOffset = collectionView.contentOffset
Expand Down Expand Up @@ -126,6 +128,7 @@ extension CategorySectionTableViewCell: UICollectionViewDataSource {

let thumbnail = thumbnails[indexPath.row]
cell.previewURL = thumbnailUrl(forThumbnail: thumbnail)
cell.selectionDecorationsHidden = selectionDecorationsHidden
cell.isAccessibilityElement = true
cell.accessibilityLabel = thumbnail.slug
return cell
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Foundation

extension RemoteSiteDesign: Thumbnail {
var urlDesktop: String? { screenshot }
var urlTablet: String? { tabletScreenshot }
var urlMobile: String? { mobileScreenshot}
}
Original file line number Diff line number Diff line change
@@ -1,49 +1,32 @@
import UIKit
import WordPressKit

extension RemoteSiteDesign: Thumbnail {
var urlDesktop: String? { screenshot }
var urlTablet: String? { tabletScreenshot }
var urlMobile: String? { mobileScreenshot}
}

class SiteDesignSection: CategorySection {
var category: RemoteSiteDesignCategory
var designs: [RemoteSiteDesign]

var categorySlug: String { category.slug }
var title: String { category.title }
var emoji: String? { category.emoji }
var description: String? { category.description }
var thumbnails: [Thumbnail] { designs }
var scrollOffset: CGPoint

init(category: RemoteSiteDesignCategory, designs: [RemoteSiteDesign]) {
self.category = category
self.designs = designs
self.scrollOffset = .zero
}
}

class SiteDesignContentCollectionViewController: FilterableCategoriesViewController, UIPopoverPresentationControllerDelegate {
class SiteDesignContentCollectionViewController: CollapsableHeaderViewController {
typealias TemplateGroup = SiteDesignRequest.TemplateGroup
typealias PreviewDevice = PreviewDeviceSelectionViewController.PreviewDevice

private let createsSite: Bool
private let templateGroups: [TemplateGroup] = [.stable, .singlePage]

let completion: SiteDesignStep.SiteDesignSelection
let restAPI = WordPressComRestApi.anonymousApi(userAgent: WPUserAgent.wordPress(), localeKey: WordPressComRestApi.LocaleKeyV2)
var selectedIndexPath: IndexPath? = nil
private let tableView: UITableView
private let completion: SiteDesignStep.SiteDesignSelection
private let restAPI = WordPressComRestApi.anonymousApi(
userAgent: WPUserAgent.wordPress(),
localeKey: WordPressComRestApi.LocaleKeyV2
)
private var sections: [SiteDesignSection] = []
internal override var categorySections: [CategorySection] { get { sections }}
private var isLoading: Bool = true {
didSet {
if isLoading {
tableView.startGhostAnimation(style: GhostCellStyle.muriel)
} else {
tableView.stopGhostAnimation()
}

override var selectedPreviewDevice: PreviewDevice {
get { .mobile }
set { /* no op */ }
tableView.reloadData()
}
}

private lazy var previewViewSelectedPreviewDevice = PreviewDevice.default

var siteDesigns = RemoteSiteDesigns() {
private var previewViewSelectedPreviewDevice = PreviewDevice.default
private var siteDesigns = RemoteSiteDesigns() {
didSet {
if oldValue.categories.count == 0 {
scrollableView.setContentOffset(.zero, animated: false)
Expand All @@ -52,26 +35,29 @@ class SiteDesignContentCollectionViewController: FilterableCategoriesViewControl
SiteDesignSection(category: category, designs: siteDesigns.designs.filter { design in design.categories.map({$0.slug}).contains(category.slug)
})
}
NSLog("sections: %@", String(describing: sections))
contentSizeWillChange()
tableView.reloadData()
}
}

var selectedDesign: RemoteSiteDesign? {
guard let sectionIndex = selectedItem?.section, let position = selectedItem?.item else { return nil }
return sections[sectionIndex].designs[position]
var selectedPreviewDevice: PreviewDevice {
get { .mobile }
set { /* no op */ }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if set does nothing, can we just

var selectedPreviewDevice: PreviewDevice {
        .mobile
}

Copy link
Contributor Author

@twstokes twstokes May 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! I'll get this fixed. This was left over from being a subclass of FilterableCategoriesViewController which required a setter. 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I see 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be resolved with this commit.

}

init(createsSite: Bool, _ completion: @escaping SiteDesignStep.SiteDesignSelection) {
self.completion = completion
self.createsSite = createsSite
tableView = UITableView(frame: .zero, style: .plain)
tableView.separatorStyle = .singleLine
tableView.separatorInset = .zero
tableView.showsVerticalScrollIndicator = false

super.init(
analyticsLocation: "site_creation",
scrollableView: tableView,
mainTitle: TextContent.mainTitle,
primaryActionTitle: createsSite ? TextContent.createSiteButton : TextContent.chooseButton,
secondaryActionTitle: TextContent.previewButton
// the primary action button is never shown
primaryActionTitle: ""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only part where CollapsableHeaderViewController didn't quite support what we needed. We'll never show a primary action, so there's no need for us to supply a title.

)
}

Expand All @@ -81,6 +67,8 @@ class SiteDesignContentCollectionViewController: FilterableCategoriesViewControl

override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CategorySectionTableViewCell.nib, forCellReuseIdentifier: CategorySectionTableViewCell.cellReuseIdentifier)
tableView.dataSource = self
navigationItem.backButtonTitle = TextContent.backButtonTitle
fetchSiteDesigns()
configureCloseButton()
Expand Down Expand Up @@ -119,39 +107,18 @@ class SiteDesignContentCollectionViewController: FilterableCategoriesViewControl
navigationItem.leftBarButtonItem = UIBarButtonItem(title: TextContent.cancelButtonTitle, style: .done, target: self, action: #selector(closeButtonTapped))
}

@objc func skipButtonTapped(_ sender: Any) {
@objc
private func closeButtonTapped(_ sender: Any) {
dismiss(animated: true)
}

@objc
private func skipButtonTapped(_ sender: Any) {
presentedViewController?.dismiss(animated: true)
SiteCreationAnalyticsHelper.trackSiteDesignSkipped()
completion(nil)
}

override func primaryActionSelected(_ sender: Any) {
guard let design = selectedDesign else {
completion(nil)
return
}
SiteCreationAnalyticsHelper.trackSiteDesignSelected(design)
completion(design)
}

override func secondaryActionSelected(_ sender: Any) {
guard let design = selectedDesign else { return }

let previewVC = SiteDesignPreviewViewController(
siteDesign: design,
selectedPreviewDevice: previewViewSelectedPreviewDevice,
createsSite: createsSite,
onDismissWithDeviceSelected: { [weak self] device in
self?.previewViewSelectedPreviewDevice = device
},
completion: completion
)

let navController = GutenbergLightNavigationController(rootViewController: previewVC)
navController.modalPresentationStyle = .pageSheet
navigationController?.present(navController, animated: true)
}

private func handleError(_ error: Error) {
SiteCreationAnalyticsHelper.trackError(error)
let titleText = TextContent.errorTitle
Expand All @@ -161,9 +128,6 @@ class SiteDesignContentCollectionViewController: FilterableCategoriesViewControl

private enum TextContent {
static let mainTitle = NSLocalizedString("Choose a theme", comment: "Title for the screen to pick a theme and homepage for a site.")
static let createSiteButton = NSLocalizedString("Create Site", comment: "Title for the button to progress with creating the site with the selected design.")
static let chooseButton = NSLocalizedString("Choose", comment: "Title for the button to progress with the selected site homepage design.")
static let previewButton = NSLocalizedString("Preview", comment: "Title for button to preview a selected homepage design.")
static let backButtonTitle = NSLocalizedString("Design", comment: "Shortened version of the main title to be used in back navigation.")
static let skipButtonTitle = NSLocalizedString("Skip", comment: "Continue without making a selection.")
static let cancelButtonTitle = NSLocalizedString("Cancel", comment: "Cancel site creation.")
Expand All @@ -173,8 +137,68 @@ class SiteDesignContentCollectionViewController: FilterableCategoriesViewControl
}

// MARK: - NoResultsViewControllerDelegate

extension SiteDesignContentCollectionViewController: NoResultsViewControllerDelegate {
func actionButtonPressed() {
fetchSiteDesigns()
}
}

// MARK: - UITableViewDataSource

extension SiteDesignContentCollectionViewController: UITableViewDataSource {

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return CategorySectionTableViewCell.estimatedCellHeight
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return isLoading ? 1 : (sections.count)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellReuseIdentifier = CategorySectionTableViewCell.cellReuseIdentifier
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as? CategorySectionTableViewCell else {
fatalError("Expected the cell with identifier \"\(cellReuseIdentifier)\" to be a \(CategorySectionTableViewCell.self). Please make sure the table view is registering the correct nib before loading the data")
}
cell.delegate = self
cell.selectionStyle = UITableViewCell.SelectionStyle.none
cell.section = isLoading ? nil : sections[indexPath.row]
cell.isGhostCell = isLoading
cell.selectionDecorationsHidden = true
cell.layer.masksToBounds = false
cell.clipsToBounds = false
cell.collectionView.allowsSelection = !isLoading
return cell
}
}

// MARK: - CategorySectionTableViewCellDelegate

extension SiteDesignContentCollectionViewController: CategorySectionTableViewCellDelegate {
func didSelectItemAt(_ position: Int, forCell cell: CategorySectionTableViewCell, slug: String) {
guard let sectionIndex = sections.firstIndex(where: { $0.categorySlug == slug }) else { return }
let design = sections[sectionIndex].designs[position]

let previewVC = SiteDesignPreviewViewController(
siteDesign: design,
selectedPreviewDevice: previewViewSelectedPreviewDevice,
createsSite: createsSite,
onDismissWithDeviceSelected: { [weak self] device in
self?.previewViewSelectedPreviewDevice = device
},
completion: completion
)

let navController = GutenbergLightNavigationController(rootViewController: previewVC)
navController.modalPresentationStyle = .pageSheet
navigationController?.present(navController, animated: true)
}

func didDeselectItem(forCell cell: CategorySectionTableViewCell) {}

func accessibilityElementDidBecomeFocused(forCell cell: CategorySectionTableViewCell) {
guard UIAccessibility.isVoiceOverRunning, let cellIndexPath = tableView.indexPath(for: cell) else { return }
tableView.scrollToRow(at: cellIndexPath, at: .middle, animated: true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Foundation

class SiteDesignSection: CategorySection {
var category: RemoteSiteDesignCategory
var designs: [RemoteSiteDesign]

var categorySlug: String { category.slug }
var title: String { category.title }
var emoji: String? { category.emoji }
var description: String? { category.description }
var thumbnails: [Thumbnail] { designs }
var scrollOffset: CGPoint

init(category: RemoteSiteDesignCategory, designs: [RemoteSiteDesign]) {
self.category = category
self.designs = designs
self.scrollOffset = .zero
}
}
12 changes: 12 additions & 0 deletions WordPress/WordPress.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2189,6 +2189,10 @@
C373D6EA280452F6008F8C26 /* SiteIntentDataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C373D6E9280452F6008F8C26 /* SiteIntentDataTests.swift */; };
C387B7A22638D66F00BDEF86 /* PostAuthorSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E2462826277B7700B99EA6 /* PostAuthorSelectorViewController.swift */; };
C38C5D8127F61D2C002F517E /* MenuItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38C5D8027F61D2C002F517E /* MenuItemTests.swift */; };
C395FB232821FE4400AE7C11 /* SiteDesignSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB222821FE4400AE7C11 /* SiteDesignSection.swift */; };
C395FB242821FE4B00AE7C11 /* SiteDesignSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB222821FE4400AE7C11 /* SiteDesignSection.swift */; };
C395FB262821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */; };
C395FB272822148400AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */; };
C396C80B280F2401006FE7AC /* SiteDesignTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C396C80A280F2401006FE7AC /* SiteDesignTests.swift */; };
C3C39B0726F50D3900B1238D /* WordPressSupportSourceTag+Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C39B0626F50D3900B1238D /* WordPressSupportSourceTag+Editor.swift */; };
C3C39B0826F50D3900B1238D /* WordPressSupportSourceTag+Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C39B0626F50D3900B1238D /* WordPressSupportSourceTag+Editor.swift */; };
Expand Down Expand Up @@ -6958,6 +6962,8 @@
C373D6E628045281008F8C26 /* SiteIntentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteIntentData.swift; sourceTree = "<group>"; };
C373D6E9280452F6008F8C26 /* SiteIntentDataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteIntentDataTests.swift; sourceTree = "<group>"; };
C38C5D8027F61D2C002F517E /* MenuItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MenuItemTests.swift; path = Menus/MenuItemTests.swift; sourceTree = "<group>"; };
C395FB222821FE4400AE7C11 /* SiteDesignSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDesignSection.swift; sourceTree = "<group>"; };
C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RemoteSiteDesign+Thumbnail.swift"; sourceTree = "<group>"; };
C396C80A280F2401006FE7AC /* SiteDesignTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDesignTests.swift; sourceTree = "<group>"; };
C3ABE791263099F7009BD402 /* WordPress 121.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 121.xcdatamodel"; sourceTree = "<group>"; };
C3C39B0626F50D3900B1238D /* WordPressSupportSourceTag+Editor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WordPressSupportSourceTag+Editor.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -10108,8 +10114,10 @@
isa = PBXGroup;
children = (
464688D5255C719500ECA61C /* Preview */,
C395FB222821FE4400AE7C11 /* SiteDesignSection.swift */,
46241C0E2540BD01002B8A12 /* SiteDesignStep.swift */,
46241C3A2540D483002B8A12 /* SiteDesignContentCollectionViewController.swift */,
C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */,
);
path = "Design Selection";
sourceTree = "<group>";
Expand Down Expand Up @@ -17731,6 +17739,7 @@
7462BFD02028C49800B552D8 /* ShareNoticeViewModel.swift in Sources */,
17A4A36920EE51870071C2CA /* Routes+Reader.swift in Sources */,
0807CB721CE670A800CDBDAC /* WPContentSearchHelper.swift in Sources */,
C395FB262821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */,
9A73B7152362FBAE004624A8 /* SiteStatsViewModel+AsyncBlock.swift in Sources */,
74AF4D7C1FE417D200E3EBFE /* PostUploadOperation.swift in Sources */,
37022D931981C19000F322B7 /* VerticallyStackedButton.m in Sources */,
Expand Down Expand Up @@ -19151,6 +19160,7 @@
E1A03EE217422DCF0085D192 /* BlogToAccount.m in Sources */,
C77FC90928009C7000726F00 /* OnboardingQuestionsPromptViewController.swift in Sources */,
8BE6F92C27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift in Sources */,
C395FB232821FE4400AE7C11 /* SiteDesignSection.swift in Sources */,
FA4F660525946B5F00EAA9F5 /* JetpackRestoreHeaderView.swift in Sources */,
FEA6517B281C491C002EA086 /* BloggingPromptsService.swift in Sources */,
436D55DF210F866900CEAA33 /* StoryboardLoadable.swift in Sources */,
Expand Down Expand Up @@ -21457,6 +21467,7 @@
FABB256B2602FC2C00C8785C /* InteractivePostView.swift in Sources */,
FABB256C2602FC2C00C8785C /* LinearGradientView.swift in Sources */,
FABB256D2602FC2C00C8785C /* WizardStep.swift in Sources */,
C395FB242821FE4B00AE7C11 /* SiteDesignSection.swift in Sources */,
FABB256E2602FC2C00C8785C /* PostPostViewController.swift in Sources */,
FABB256F2602FC2C00C8785C /* QuickStartSpotlightView.swift in Sources */,
FABB25702602FC2C00C8785C /* ReaderReblogAction.swift in Sources */,
Expand Down Expand Up @@ -21663,6 +21674,7 @@
FABB26172602FC2C00C8785C /* MediaExternalExporter.swift in Sources */,
FABB26182602FC2C00C8785C /* RegisterDomainDetailsViewModel+SectionDefinitions.swift in Sources */,
FABB26192602FC2C00C8785C /* ActionRow.swift in Sources */,
C395FB272822148400AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */,
9815D0B426B49A0600DF7226 /* Comment+CoreDataProperties.swift in Sources */,
FABB261A2602FC2C00C8785C /* AppSettingsViewController.swift in Sources */,
FABB261B2602FC2C00C8785C /* ReaderPostService+PostsV2.swift in Sources */,
Expand Down
Loading