diff --git a/WordPress/Classes/ViewRelated/Blog/NoResultsViewController.swift b/WordPress/Classes/ViewRelated/Blog/NoResultsViewController.swift index d981641484ec..afb8cf4393c0 100644 --- a/WordPress/Classes/ViewRelated/Blog/NoResultsViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/NoResultsViewController.swift @@ -7,7 +7,8 @@ import UIKit /// A view to show when there are no results for a given situation. /// Ex: My Sites > account has no sites; My Sites > all sites are hidden. -/// The image, title, and action button will always show. +/// The image and title will always show. +/// The action button is shown by default, but will be hidden if button title is not provided. /// The subtitle is optional and will only show if provided. /// @objc class NoResultsViewController: NUXViewController { @@ -42,10 +43,10 @@ import UIKit /// /// - Parameters: /// - title: Main descriptive text. Required. - /// - buttonTitle: Title of action button. Required. + /// - buttonTitle: Title of action button. Optional. /// - subtitle: Secondary descriptive text. Optional. /// - image: Name of image file to use. Optional. - @objc func configure(title: String, buttonTitle: String, subtitle: String? = nil, image: String? = nil) { + @objc func configure(title: String, buttonTitle: String? = nil, subtitle: String? = nil, image: String? = nil) { titleText = title subtitleText = subtitle buttonText = buttonTitle @@ -67,17 +68,21 @@ import UIKit /// Use the values provided in the actual elements. private func configureView() { - guard let titleText = titleText, - let buttonText = buttonText else { + guard let titleText = titleText else { return } titleLabel.text = titleText subtitleLabel.text = subtitleText - actionButton?.setTitle(buttonText, for: UIControlState()) - actionButton?.setTitle(buttonText, for: .highlighted) - actionButton?.titleLabel?.adjustsFontForContentSizeCategory = true - actionButton?.accessibilityIdentifier = accessibilityIdentifier(for: buttonText) + + if let buttonText = buttonText { + actionButton?.setTitle(buttonText, for: UIControlState()) + actionButton?.setTitle(buttonText, for: .highlighted) + actionButton?.titleLabel?.adjustsFontForContentSizeCategory = true + actionButton?.accessibilityIdentifier = accessibilityIdentifier(for: buttonText) + } else { + actionButton.isHidden = true + } if let imageName = imageName { imageView.image = UIImage(named: imageName) diff --git a/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainSearchTableViewCell.swift b/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainSearchTableViewCell.swift index 238b7ba8a267..3a1d69793026 100644 --- a/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainSearchTableViewCell.swift +++ b/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainSearchTableViewCell.swift @@ -29,7 +29,7 @@ class SiteCreationDomainSearchTableViewCell: UITableViewCell { textField?.text = placeholder textField?.delegate = self textField?.contentInsets = Constants.textInsetsWithIcon - textField?.placeholder = NSLocalizedString("Type to get more suggestions", comment: "Placeholder text for domain search during site creation.") + textField?.placeholder = NSLocalizedString("Type a keyword for more ideas", comment: "Placeholder text for domain search during site creation.") textField?.accessibilityIdentifier = "Domain search field" if let searchIcon = textField?.leftViewImage { diff --git a/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainsTableViewController.swift b/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainsTableViewController.swift index bc5b222e1a13..bfb70ffe0049 100644 --- a/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainsTableViewController.swift +++ b/WordPress/Classes/ViewRelated/NUX/SiteCreationDomainsTableViewController.swift @@ -8,21 +8,39 @@ protocol SiteCreationDomainsTableViewControllerDelegate { class SiteCreationDomainsTableViewController: NUXTableViewController { + // MARK: - Properties + open var siteName: String? open var delegate: SiteCreationDomainsTableViewControllerDelegate? + private var noResultsViewController: NoResultsViewController? private var service: DomainsService? private var siteTitleSuggestions: [String] = [] private var searchSuggestions: [String] = [] private var isSearching: Bool = false private var selectedCell: UITableViewCell? + // API returned no domain suggestions. + private var noSuggestions: Bool = false + + fileprivate enum ViewPadding: CGFloat { + case noResultsView = 60 + } + + // MARK: - Init + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + override func awakeFromNib() { super.awakeFromNib() tableView.register(UINib(nibName: "SiteCreationDomainSearchTableViewCell", bundle: nil), forCellReuseIdentifier: SiteCreationDomainSearchTableViewCell.cellIdentifier) setupBackgroundTapGestureRecognizer() } + // MARK: - View + override func viewDidLoad() { super.viewDidLoad() @@ -35,7 +53,8 @@ class SiteCreationDomainsTableViewController: NUXTableViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - // only procede with initial search if we don't have site title suggestions yet (hopefully only the first time) + // only procede with initial search if we don't have site title suggestions yet + // (hopefully only the first time) guard siteTitleSuggestions.count < 1, let nameToSearch = siteName else { return @@ -69,14 +88,25 @@ class SiteCreationDomainsTableViewController: NUXTableViewController { let service = DomainsService(managedObjectContext: ContextManager.sharedInstance().mainContext, remote: DomainsServiceRemote(wordPressComRestApi: api)) SVProgressHUD.show(withStatus: NSLocalizedString("Loading domains", comment: "Shown while the app waits for the domain suggestions web service to return during the site creation process.")) + service.getDomainSuggestions(base: searchTerm, success: { [weak self] (suggestions) in self?.isSearching = false + self?.noSuggestions = false SVProgressHUD.dismiss() + self?.tableView.separatorStyle = .singleLine + // Dismiss the keyboard so the full results list can be seen. + self?.view.endEditing(true) addSuggestions(suggestions) }) { [weak self] (error) in DDLogError("Error getting Domain Suggestions: \(error.localizedDescription)") self?.isSearching = false + self?.noSuggestions = true SVProgressHUD.dismiss() + self?.tableView.separatorStyle = .none + // Dismiss the keyboard so the full no results view can be seen. + self?.view.endEditing(true) + // Add no suggestions to display the no results view. + addSuggestions([]) } } @@ -94,7 +124,7 @@ class SiteCreationDomainsTableViewController: NUXTableViewController { } } -// MARK: UITableViewDataSource +// MARK: - UITableViewDataSource extension SiteCreationDomainsTableViewController { fileprivate enum Sections: Int { @@ -117,6 +147,9 @@ extension SiteCreationDomainsTableViewController { Sections.searchField.rawValue: return 1 case Sections.suggestions.rawValue: + if noSuggestions == true { + return 1 + } return searchSuggestions.count > 0 ? searchSuggestions.count : siteTitleSuggestions.count default: return 0 @@ -133,17 +166,35 @@ extension SiteCreationDomainsTableViewController { case Sections.suggestions.rawValue: fallthrough default: - let suggestion: String - if searchSuggestions.count > 0 { - suggestion = searchSuggestions[indexPath.row] + if noSuggestions == true { + cell = noResultsCell() } else { - suggestion = siteTitleSuggestions[indexPath.row] + let suggestion: String + if searchSuggestions.count > 0 { + suggestion = searchSuggestions[indexPath.row] + } else { + suggestion = siteTitleSuggestions[indexPath.row] + } + cell = suggestionCell(domain: suggestion) } - cell = suggestionCell(domain: suggestion) } return cell } + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + + if indexPath.section == Sections.suggestions.rawValue && noSuggestions == true { + // Calculate the height of the no results cell from the bottom of + // the search field to the screen bottom, minus some padding. + let searchFieldRect = tableView.rect(forSection: Sections.searchField.rawValue) + let searchFieldBottom = searchFieldRect.origin.y + searchFieldRect.height + let screenBottom = UIScreen.main.bounds.height + return screenBottom - searchFieldBottom - ViewPadding.noResultsView.rawValue + } + + return super.tableView(tableView, heightForRowAt: indexPath) + } + override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { if section == Sections.suggestions.rawValue { let footer = UIView() @@ -179,6 +230,13 @@ extension SiteCreationDomainsTableViewController { return cell } + private func noResultsCell() -> UITableViewCell { + let cell = UITableViewCell() + addNoResultsTo(cell: cell) + cell.isUserInteractionEnabled = false + return cell + } + private func suggestionCell(domain: String) -> UITableViewCell { let cell = UITableViewCell() @@ -199,7 +257,46 @@ extension SiteCreationDomainsTableViewController { } } -// MARK: UITableViewDelegate +// MARK: - NoResultsViewController Extension + +private extension SiteCreationDomainsTableViewController { + + func addNoResultsTo(cell: UITableViewCell) { + if noResultsViewController == nil { + instantiateNoResultsViewController() + } + + guard let noResultsViewController = noResultsViewController else { + return + } + + noResultsViewController.view.frame = cell.frame + cell.contentView.addSubview(noResultsViewController.view) + + addChildViewController(noResultsViewController) + noResultsViewController.didMove(toParentViewController: self) + } + + func removeNoResultsFromView() { + noSuggestions = false + tableView.reloadSections(IndexSet(integer: Sections.suggestions.rawValue), with: .automatic) + noResultsViewController?.view.removeFromSuperview() + noResultsViewController?.removeFromParentViewController() + } + + func instantiateNoResultsViewController() { + let noResultsSB = UIStoryboard(name: "NoResults", bundle: nil) + noResultsViewController = noResultsSB.instantiateViewController(withIdentifier: "NoResults") as? NoResultsViewController + + let title = NSLocalizedString("We couldn't find any available address with the words you entered - let's try again.", comment: "Primary message shown when there are no domains that match the user entered text.") + let subtitle = NSLocalizedString("Enter different words above and we'll look for an address that matches it.", comment: "Secondary message shown when there are no domains that match the user entered text.") + + noResultsViewController?.configure(title: title, buttonTitle: nil, subtitle: subtitle) + } + +} + +// MARK: - UITableViewDelegate extension SiteCreationDomainsTableViewController { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { @@ -234,11 +331,12 @@ extension SiteCreationDomainsTableViewController { } } -// MARK: SiteCreationDomainSearchTableViewCellDelegate +// MARK: - SiteCreationDomainSearchTableViewCellDelegate extension SiteCreationDomainsTableViewController: SiteCreationDomainSearchTableViewCellDelegate { func startSearch(for searchTerm: String) { + removeNoResultsFromView() delegate?.newSearchStarted() guard searchTerm.count > 0 else { diff --git a/WordPress/Classes/ViewRelated/Views/NoResults.storyboard b/WordPress/Classes/ViewRelated/Views/NoResults.storyboard index 95e274f0dd89..c3dce7409d0d 100644 --- a/WordPress/Classes/ViewRelated/Views/NoResults.storyboard +++ b/WordPress/Classes/ViewRelated/Views/NoResults.storyboard @@ -19,7 +19,7 @@ - +