From 203d499e9dd4f00927669c4b2cdc1e4b65a03d41 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 10 Oct 2023 11:32:53 -0400 Subject: [PATCH 1/2] Address TODOs in AbstractPostListViewController --- .../Post/AbstractPostListViewController.swift | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift index d1eb6df8f35d..26c782a3579e 100644 --- a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift @@ -5,31 +5,6 @@ import WordPressShared import wpxmlrpc import WordPressFlux -// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. -// Consider refactoring the code to use the non-optional operators. -fileprivate func < (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l < r - case (nil, _?): - return true - default: - return false - } -} - -// FIXME: comparison operators with optionals were removed from the Swift Standard Libary. -// Consider refactoring the code to use the non-optional operators. -fileprivate func > (lhs: T?, rhs: T?) -> Bool { - switch (lhs, rhs) { - case let (l?, r?): - return l > r - default: - return rhs < lhs - } -} - - class AbstractPostListViewController: UIViewController, WPContentSyncHelperDelegate, UISearchControllerDelegate, @@ -609,7 +584,7 @@ class AbstractPostListViewController: UIViewController, // Reset the filter to only show the latest sync point, based on the oldest post date in the posts just synced. // Note: Getting oldest date manually as the API may return results out of order if there are // differing time offsets in the created dates. - let oldestPost = posts.min {$0.date_created_gmt < $1.date_created_gmt} + let oldestPost = posts.min { ($0.date_created_gmt ?? .distantPast) < ($1.date_created_gmt ?? .distantPast) } filter.oldestPostDate = oldestPost?.date_created_gmt filter.hasMore = posts.count >= options.number.intValue @@ -826,7 +801,7 @@ class AbstractPostListViewController: UIViewController, // MARK: - Searching @objc func isSearching() -> Bool { - return searchController.isActive && currentSearchTerm()?.count > 0 + return searchController.isActive && !(currentSearchTerm() ?? "").isEmpty } @objc func currentSearchTerm() -> String? { From c34ae0c5a5d49a171c8da51f9e75ff2432082c69 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 11 Oct 2023 22:57:40 -0400 Subject: [PATCH 2/2] The initial native search implementation --- .../Pages/PageListViewController.swift | 71 ++------ .../ViewRelated/Pages/Pages.storyboard | 102 +---------- .../Post/AbstractPostListViewController.swift | 159 +++++++----------- .../Post/PostListViewController.swift | 81 +-------- .../Post/PostSearchViewController.swift | 20 +++ .../Classes/ViewRelated/Post/Posts.storyboard | 104 ------------ .../ViewRelated/System/FilterTabBar.swift | 5 + WordPress/WordPress.xcodeproj/project.pbxproj | 12 +- 8 files changed, 123 insertions(+), 431 deletions(-) create mode 100644 WordPress/Classes/ViewRelated/Post/PostSearchViewController.swift delete mode 100644 WordPress/Classes/ViewRelated/Post/Posts.storyboard diff --git a/WordPress/Classes/ViewRelated/Pages/PageListViewController.swift b/WordPress/Classes/ViewRelated/Pages/PageListViewController.swift index 28bafc1cca01..9640cfcee357 100644 --- a/WordPress/Classes/ViewRelated/Pages/PageListViewController.swift +++ b/WordPress/Classes/ViewRelated/Pages/PageListViewController.swift @@ -70,28 +70,16 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe return BlockEditorSettingsService(blog: blog, coreDataStack: ContextManager.shared) }() - // MARK: - GUI - - @IBOutlet weak var filterTabBarTopConstraint: NSLayoutConstraint! - @IBOutlet weak var filterTabBariOS10TopConstraint: NSLayoutConstraint! - @IBOutlet weak var filterTabBarBottomConstraint: NSLayoutConstraint! - @IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint! - // MARK: - Convenience constructors @objc class func controllerWithBlog(_ blog: Blog) -> PageListViewController { - - let storyBoard = UIStoryboard(name: "Pages", bundle: Bundle.main) - let controller = storyBoard.instantiateViewController(withIdentifier: "PageListViewController") as! PageListViewController - - controller.blog = blog - controller.restorationClass = self - + let vc = PageListViewController() + vc.blog = blog + vc.restorationClass = self if QuickStartTourGuide.shared.isCurrentElement(.pages) { - controller.filterSettings.setFilterWithPostStatus(BasePost.Status.publish) + vc.filterSettings.setFilterWithPostStatus(BasePost.Status.publish) } - - return controller + return vc } static func showForBlog(_ blog: Blog, from sourceController: UIViewController) { @@ -135,13 +123,6 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe // MARK: - UIViewController - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - super.refreshNoResultsViewController = { [weak self] noResultsViewController in - self?.handleRefreshNoResultsViewController(noResultsViewController) - } - super.tableViewController = (segue.destination as! UITableViewController) - } - override func viewDidLoad() { super.viewDidLoad() @@ -153,9 +134,11 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe title = NSLocalizedString("Pages", comment: "Title of the screen showing the list of pages for a blog.") - configureFilterBarTopConstraint() - createButtonCoordinator.add(to: view, trailingAnchor: view.safeAreaLayoutGuide.trailingAnchor, bottomAnchor: view.safeAreaLayoutGuide.bottomAnchor) + + refreshNoResultsViewController = { [weak self] in + self?.handleRefreshNoResultsViewController($0) + } } override func viewWillAppear(_ animated: Bool) { @@ -189,10 +172,6 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe // MARK: - Configuration - private func configureFilterBarTopConstraint() { - filterTabBariOS10TopConstraint.isActive = false - } - override func configureTableView() { tableView.accessibilityIdentifier = "PagesTable" tableView.estimatedRowHeight = Constant.Size.pageCellEstimatedRowHeight @@ -208,16 +187,6 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe tableView.register(restorePageCellNib, forCellReuseIdentifier: Constant.Identifiers.restorePageCellIdentifier) tableView.register(TemplatePageTableViewCell.self, forCellReuseIdentifier: Constant.Identifiers.templatePageCellIdentifier) - - WPStyleGuide.configureColors(view: view, tableView: tableView) - } - - override func configureSearchController() { - super.configureSearchController() - - tableView.tableHeaderView = searchController.searchBar - - tableView.verticalScrollIndicatorInsets.top = searchController.searchBar.bounds.height } override func configureAuthorFilter() { @@ -230,10 +199,6 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe } fileprivate func beginRefreshingManually() { - guard let refreshControl = refreshControl else { - return - } - refreshControl.beginRefreshing() tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentOffset.y - refreshControl.frame.size.height), animated: true) } @@ -955,7 +920,7 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe self?.refreshAndReload() self?.handleHomepageSettingsSuccess() }, failure: { error in - self?.refreshControl?.endRefreshing() + self?.refreshControl.endRefreshing() self?.handleHomepageSettingsFailure() }) } @@ -988,7 +953,7 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe self?.refreshAndReload() self?.handleHomepagePostsPageSettingsSuccess() }, failure: { error in - self?.refreshControl?.endRefreshing() + self?.refreshControl.endRefreshing() self?.handleHomepageSettingsFailure() }) } @@ -1043,14 +1008,6 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe // MARK: - UISearchControllerDelegate - override func willPresentSearchController(_ searchController: UISearchController) { - super.willPresentSearchController(searchController) - - filterTabBar.alpha = WPAlphaZero - - tableView.contentInset.top = -searchController.searchBar.bounds.height - } - override func updateSearchResults(for searchController: UISearchController) { super.updateSearchResults(for: searchController) } @@ -1066,11 +1023,7 @@ class PageListViewController: AbstractPostListViewController, UIViewControllerRe } func didDismissSearchController(_ searchController: UISearchController) { - UIView.animate(withDuration: Animations.searchDismissDuration, delay: 0, options: .curveLinear, animations: { - self.filterTabBar.alpha = WPAlphaFull - }) { _ in - self.hideNoResultsView() - } + self.hideNoResultsView() } enum Animations { diff --git a/WordPress/Classes/ViewRelated/Pages/Pages.storyboard b/WordPress/Classes/ViewRelated/Pages/Pages.storyboard index 95f8b6d5052f..4c0fddd24d2a 100644 --- a/WordPress/Classes/ViewRelated/Pages/Pages.storyboard +++ b/WordPress/Classes/ViewRelated/Pages/Pages.storyboard @@ -1,101 +1,12 @@ - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -126,7 +37,7 @@ - + @@ -168,4 +79,9 @@ + + + + + diff --git a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift index 26c782a3579e..6f4693e4525a 100644 --- a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift @@ -6,19 +6,18 @@ import wpxmlrpc import WordPressFlux class AbstractPostListViewController: UIViewController, - WPContentSyncHelperDelegate, - UISearchControllerDelegate, - UISearchResultsUpdating, - WPTableViewHandlerDelegate, - // This protocol is not in an extension so that subclasses can override noConnectionMessage() - NetworkAwareUI { + WPContentSyncHelperDelegate, + UISearchControllerDelegate, + UISearchResultsUpdating, + WPTableViewHandlerDelegate, + NetworkAwareUI // This protocol is not in an extension so that subclasses can override noConnectionMessage() +{ fileprivate static let postsControllerRefreshInterval = TimeInterval(300) fileprivate static let HTTPErrorCodeForbidden = Int(403) fileprivate static let postsFetchRequestBatchSize = Int(10) fileprivate static let pagesNumberOfLoadedElement = Int(100) fileprivate static let postsLoadMoreThreshold = Int(4) - fileprivate static let preferredFiltersPopoverContentSize = CGSize(width: 320.0, height: 220.0) fileprivate static let defaultHeightForFooterView = CGFloat(44.0) @@ -45,7 +44,7 @@ class AbstractPostListViewController: UIViewController, /// to the subclass to define this property. /// @objc var refreshNoResultsViewController: ((NoResultsViewController) -> ())! - @objc var tableViewController: UITableViewController! + let tableViewController = UITableViewController(style: .grouped) @objc var reloadTableViewBeforeAppearing = false @objc var tableView: UITableView { @@ -54,11 +53,7 @@ class AbstractPostListViewController: UIViewController, } } - @objc var refreshControl: UIRefreshControl? { - get { - return self.tableViewController.refreshControl - } - } + let refreshControl = UIRefreshControl() @objc lazy var tableViewHandler: WPTableViewHandler = { let tableViewHandler = WPTableViewHandler(tableView: self.tableView) @@ -102,7 +97,9 @@ class AbstractPostListViewController: UIViewController, @objc var postListFooterView: PostListFooterView! - @IBOutlet var filterTabBar: FilterTabBar! + let filterTabBar = FilterTabBar() + + private let searchResultsViewController = PostSearchViewController() @objc var searchController: UISearchController! @objc var recentlyTrashedPostObjectIDs = [NSManagedObjectID]() // IDs of trashed posts. Cleared on refresh or when filter changes. @@ -115,13 +112,23 @@ class AbstractPostListViewController: UIViewController, private var atLeastSyncedOnce = false + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + + edgesForExtendedLayout = .all + extendedLayoutIncludesOpaqueBars = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() - refreshControl?.addTarget(self, action: #selector(refresh(_:)), for: .valueChanged) - + configureTableViewController() configureFilterBar() configureTableView() configureFooterView() @@ -130,10 +137,9 @@ class AbstractPostListViewController: UIViewController, configureSearchController() configureSearchHelper() configureAuthorFilter() - configureSearchBackingView() configureGhostableTableView() + configureNavigationBarAppearance() - WPStyleGuide.configureColors(view: view, tableView: tableView) tableView.reloadData() observeNetworkStatus() @@ -149,30 +155,20 @@ class AbstractPostListViewController: UIViewController, tableView.reloadData() } - filterTabBar.layoutIfNeeded() updateSelectedFilter() refreshResults() - } - - fileprivate var searchBarHeight: CGFloat { - return searchController.searchBar.bounds.height + view.safeAreaInsets.top - } - - fileprivate func localKeyboardFrameFromNotification(_ notification: Foundation.Notification) -> CGRect { - let key = UIResponder.keyboardFrameEndUserInfoKey - guard let keyboardFrame = (notification.userInfo?[key] as? NSValue)?.cgRectValue else { - return .zero - } - // Convert the frame from window coordinates - return view.convert(keyboardFrame, from: nil) + // Show it initially but allow the user to dismiss it by scrolling + navigationItem.hidesSearchBarWhenScrolling = false } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) automaticallySyncIfAppropriate() + + navigationItem.hidesSearchBarWhenScrolling = true } override func viewWillDisappear(_ animated: Bool) { @@ -193,6 +189,18 @@ class AbstractPostListViewController: UIViewController, return type(of: self).defaultHeightForFooterView } + private func configureTableViewController() { + addChild(tableViewController) + view.addSubview(tableViewController.view) + tableViewController.view.translatesAutoresizingMaskIntoConstraints = false + view.pinSubviewToAllEdges(tableViewController.view) + tableViewController.didMove(toParent: self) + + tableView.backgroundColor = .white + tableView.refreshControl = refreshControl + refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged) + } + func configureNavbar() { // IMPORTANT: this code makes sure that the back button in WPPostViewController doesn't show // this VC's title. @@ -203,10 +211,14 @@ class AbstractPostListViewController: UIViewController, func configureFilterBar() { WPStyleGuide.configureFilterTabBar(filterTabBar) - + filterTabBar.isLayoutMarginsRelativeArrangement = false + filterTabBar.backgroundColor = .clear filterTabBar.items = filterSettings.availablePostListFilters() - filterTabBar.addTarget(self, action: #selector(selectedFilterDidChange(_:)), for: .valueChanged) + + filterTabBar.translatesAutoresizingMaskIntoConstraints = true + filterTabBar.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 40) + tableView.tableHeaderView = filterTabBar } func configureTableView() { @@ -241,7 +253,7 @@ class AbstractPostListViewController: UIViewController, } let _ = DispatchDelayedAction(delay: .milliseconds(500)) { [weak self] in - self?.refreshControl?.endRefreshing() + self?.refreshControl.endRefreshing() } hideNoResultsView() @@ -249,66 +261,34 @@ class AbstractPostListViewController: UIViewController, stopGhostIfConnectionIsNotAvailable() showNoResultsView() } - - updateBackgroundColor() - } - - // Update controller's background color to avoid a white line below - // the search bar - due to a margin between searchBar and the tableView - private func updateBackgroundColor() { - if searchController.isActive && emptyResults { - view.backgroundColor = noResultsViewController.view.backgroundColor - } else { - view.backgroundColor = tableView.backgroundColor - } } func configureAuthorFilter() { fatalError("You should implement this method in the subclass") } - /// Subclasses should override this method (and call super) to insert the - /// search controller's search bar into the view hierarchy - @objc func configureSearchController() { - // Required for insets to work out correctly when the search bar becomes active - extendedLayoutIncludesOpaqueBars = true - definesPresentationContext = true - - searchController = UISearchController(searchResultsController: nil) - searchController.obscuresBackgroundDuringPresentation = false - + private func configureSearchController() { + searchController = UISearchController(searchResultsController: searchResultsViewController) searchController.delegate = self searchController.searchResultsUpdater = self + searchController.showsSearchResultsController = true - WPStyleGuide.configureSearchBar(searchController.searchBar) - - searchController.searchBar.autocorrectionType = .default - } + definesPresentationContext = true - fileprivate func configureInitialScrollInsets() { - tableView.layoutIfNeeded() - tableView.contentInset = .zero - tableView.scrollIndicatorInsets = .zero - tableView.contentOffset = .zero + navigationItem.searchController = searchController } - fileprivate func configureSearchBackingView() { - // This mask view is required to cover the area between the top of the search - // bar and the top of the screen on an iPhone X and on iOS 10. - let topAnchor = view.safeAreaLayoutGuide.topAnchor - - let backingView = UIView() - view.addSubview(backingView) + private func configureNavigationBarAppearance() { + let standardAppearance = UINavigationBarAppearance() + standardAppearance.configureWithDefaultBackground() - backingView.backgroundColor = searchController.searchBar.barTintColor - backingView.translatesAutoresizingMaskIntoConstraints = false + let scrollEdgeAppearance = UINavigationBarAppearance() + scrollEdgeAppearance.configureWithTransparentBackground() - NSLayoutConstraint.activate([ - backingView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - backingView.trailingAnchor.constraint(equalTo: view.trailingAnchor), - backingView.topAnchor.constraint(equalTo: view.topAnchor), - backingView.bottomAnchor.constraint(equalTo: topAnchor) - ]) + navigationItem.standardAppearance = standardAppearance + navigationItem.compactAppearance = standardAppearance + navigationItem.scrollEdgeAppearance = scrollEdgeAppearance + navigationItem.compactScrollEdgeAppearance = scrollEdgeAppearance } func configureGhostableTableView() { @@ -320,7 +300,7 @@ class AbstractPostListViewController: UIViewController, ghostableTableView.widthAnchor.constraint(equalTo: tableView.widthAnchor), ghostableTableView.heightAnchor.constraint(equalTo: tableView.heightAnchor), ghostableTableView.leadingAnchor.constraint(equalTo: tableView.leadingAnchor), - ghostableTableView.topAnchor.constraint(equalTo: searchController.searchBar.bottomAnchor) + ghostableTableView.topAnchor.constraint(equalTo: tableView.topAnchor) ]) ghostableTableView.backgroundColor = .white @@ -469,13 +449,6 @@ class AbstractPostListViewController: UIViewController, refreshResults() } - @objc func resetTableViewContentOffset(_ animated: Bool = false) { - // Reset the tableView contentOffset to the top before we make any dataSource changes. - var tableOffset = tableView.contentOffset - tableOffset.y = -tableView.contentInset.top - tableView.setContentOffset(tableOffset, animated: animated) - } - @objc func predicateForFetchRequest() -> NSPredicate { fatalError("You should implement this method in the subclass") } @@ -712,7 +685,7 @@ class AbstractPostListViewController: UIViewController, } func syncContentEnded(_ syncHelper: WPContentSyncHelper) { - refreshControl?.endRefreshing() + refreshControl.endRefreshing() postListFooterView.showSpinner(false) noResultsViewController.removeFromView() @@ -1081,7 +1054,6 @@ class AbstractPostListViewController: UIViewController, @objc func refreshAndReload() { recentlyTrashedPostObjectIDs.removeAll() updateSelectedFilter() - resetTableViewContentOffset() updateAndPerformFetchRequestRefreshingResults() } @@ -1111,8 +1083,6 @@ class AbstractPostListViewController: UIViewController, syncItemsWithUserInteraction(false) - configureInitialScrollInsets() - WPAnalytics.track(.postListStatusFilterChanged, withProperties: propertiesForAnalytics()) } @@ -1125,12 +1095,9 @@ class AbstractPostListViewController: UIViewController, func willDismissSearchController(_ searchController: UISearchController) { searchController.searchBar.text = nil searchHelper.searchCanceled() - - configureInitialScrollInsets() } func updateSearchResults(for searchController: UISearchController) { - resetTableViewContentOffset() searchHelper.searchUpdated(searchController.searchBar.text) } diff --git a/WordPress/Classes/ViewRelated/Post/PostListViewController.swift b/WordPress/Classes/ViewRelated/Post/PostListViewController.swift index ae8534708a0a..17fe3c1a6796 100644 --- a/WordPress/Classes/ViewRelated/Post/PostListViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/PostListViewController.swift @@ -25,12 +25,6 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe private let postCardEstimatedRowHeight = CGFloat(300.0) private let postListHeightForFooterView = CGFloat(50.0) - @IBOutlet var searchWrapperView: UIView! - @IBOutlet weak var filterTabBarTopConstraint: NSLayoutConstraint! - @IBOutlet weak var filterTabBariOS10TopConstraint: NSLayoutConstraint! - @IBOutlet weak var filterTabBarBottomConstraint: NSLayoutConstraint! - @IBOutlet weak var tableViewTopConstraint: NSLayoutConstraint! - private var database: UserPersistentRepository = UserPersistentStoreFactory.instance() private lazy var _tableViewHandler: PostListTableViewHandler = { @@ -78,13 +72,10 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe // MARK: - Convenience constructors @objc class func controllerWithBlog(_ blog: Blog) -> PostListViewController { - - let storyBoard = UIStoryboard(name: "Posts", bundle: Bundle.main) - let controller = storyBoard.instantiateViewController(withIdentifier: "PostListViewController") as! PostListViewController - controller.blog = blog - controller.restorationClass = self - - return controller + let vc = PostListViewController() + vc.blog = blog + vc.restorationClass = self + return vc } static func showForBlog(_ blog: Blog, from sourceController: UIViewController, withPostStatus postStatus: BasePost.Status? = nil) { @@ -127,23 +118,11 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe // MARK: - UIViewController - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - - precondition(segue.destination is UITableViewController) - - super.refreshNoResultsViewController = { [weak self] noResultsViewController in - self?.handleRefreshNoResultsViewController(noResultsViewController) - } - - super.tableViewController = (segue.destination as! UITableViewController) - } - override func viewDidLoad() { super.viewDidLoad() title = NSLocalizedString("Posts", comment: "Title of the screen showing the list of posts for a blog.") - configureFilterBarTopConstraint() updateGhostableTableViewOptions() configureNavigationButtons() @@ -152,6 +131,10 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe listenForAppComingToForeground() createButtonCoordinator.add(to: view, trailingAnchor: view.safeAreaLayoutGuide.trailingAnchor, bottomAnchor: view.safeAreaLayoutGuide.bottomAnchor) + + refreshNoResultsViewController = { [weak self] in + self?.handleRefreshNoResultsViewController($0) + } } private lazy var createButtonCoordinator: CreateButtonCoordinator = { @@ -240,11 +223,6 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe return headerView } - private func configureFilterBarTopConstraint() { - filterTabBariOS10TopConstraint.isActive = false - } - - override func selectedFilterDidChange(_ filterBar: FilterTabBar) { updateGhostableTableViewOptions() super.selectedFilterDidChange(filterBar) @@ -290,8 +268,6 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe let headerNib = UINib(nibName: ActivityListSectionHeaderView.identifier, bundle: nil) tableView.register(headerNib, forHeaderFooterViewReuseIdentifier: ActivityListSectionHeaderView.identifier) - - WPStyleGuide.configureColors(view: view, tableView: tableView) } override func configureGhostableTableView() { @@ -319,28 +295,6 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe updateAuthorFilter() } - override func configureSearchController() { - super.configureSearchController() - - searchWrapperView.addSubview(searchController.searchBar) - - tableView.verticalScrollIndicatorInsets.top = searchController.searchBar.bounds.height - - updateTableHeaderSize() - } - - fileprivate func updateTableHeaderSize() { - if searchController.isActive { - // Account for the search bar being moved to the top of the screen. - searchWrapperView.frame.size.height = 0 - } else { - searchWrapperView.frame.size.height = searchController.searchBar.bounds.height - } - - // Resetting the tableHeaderView is necessary to get the new height to take effect - tableView.tableHeaderView = searchWrapperView - } - func showCompactOrDefault() { updateGhostableTableViewOptions() @@ -761,18 +715,8 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe super.updateForLocalPostsMatchingSearchText() } - override func willPresentSearchController(_ searchController: UISearchController) { - super.willPresentSearchController(searchController) - - self.filterTabBar.alpha = WPAlphaZero - } - func didPresentSearchController(_ searchController: UISearchController) { - updateTableHeaderSize() _tableViewHandler.isSearching = true - - tableView.verticalScrollIndicatorInsets.top = searchWrapperView.bounds.height - tableView.contentInset.top = 0 } override func sortDescriptorsForFetchRequest() -> [NSSortDescriptor] { @@ -786,18 +730,9 @@ class PostListViewController: AbstractPostListViewController, UIViewControllerRe override func willDismissSearchController(_ searchController: UISearchController) { _tableViewHandler.isSearching = false - _tableViewHandler.refreshTableView() super.willDismissSearchController(searchController) } - func didDismissSearchController(_ searchController: UISearchController) { - updateTableHeaderSize() - - UIView.animate(withDuration: Animations.searchDismissDuration) { - self.filterTabBar.alpha = WPAlphaFull - } - } - enum Animations { static let searchDismissDuration: TimeInterval = 0.3 } diff --git a/WordPress/Classes/ViewRelated/Post/PostSearchViewController.swift b/WordPress/Classes/ViewRelated/Post/PostSearchViewController.swift new file mode 100644 index 000000000000..2f527ca347c0 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Post/PostSearchViewController.swift @@ -0,0 +1,20 @@ +import UIKit + +final class PostSearchViewController: UITableViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellID") + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + 10 + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) + cell.textLabel?.text = indexPath.row.description + return cell + } +} diff --git a/WordPress/Classes/ViewRelated/Post/Posts.storyboard b/WordPress/Classes/ViewRelated/Post/Posts.storyboard deleted file mode 100644 index ea2add84b74b..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Posts.storyboard +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/Classes/ViewRelated/System/FilterTabBar.swift b/WordPress/Classes/ViewRelated/System/FilterTabBar.swift index 7cd9dd8b8253..184da1982ab1 100644 --- a/WordPress/Classes/ViewRelated/System/FilterTabBar.swift +++ b/WordPress/Classes/ViewRelated/System/FilterTabBar.swift @@ -66,6 +66,11 @@ class FilterTabBar: UIControl { } } + var isLayoutMarginsRelativeArrangement: Bool { + get { stackView.isLayoutMarginsRelativeArrangement } + set { stackView.isLayoutMarginsRelativeArrangement = newValue } + } + private var tabBarHeightConstraint: NSLayoutConstraint! { didSet { if let oldValue = oldValue { diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 76cd60973959..9c88a6a9c650 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -467,6 +467,8 @@ 0CD382832A4B699E00612173 /* DashboardBlazeCardCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD382822A4B699E00612173 /* DashboardBlazeCardCellViewModel.swift */; }; 0CD382842A4B699E00612173 /* DashboardBlazeCardCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD382822A4B699E00612173 /* DashboardBlazeCardCellViewModel.swift */; }; 0CD382862A4B6FCF00612173 /* DashboardBlazeCardCellViewModelTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD382852A4B6FCE00612173 /* DashboardBlazeCardCellViewModelTest.swift */; }; + 0CD9CC9F2AD73A560044A33C /* PostSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9CC9E2AD73A560044A33C /* PostSearchViewController.swift */; }; + 0CD9CCA02AD73A560044A33C /* PostSearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CD9CC9E2AD73A560044A33C /* PostSearchViewController.swift */; }; 0CDEC40C2A2FAF0500BB3A91 /* DashboardBlazeCampaignsCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CDEC40B2A2FAF0500BB3A91 /* DashboardBlazeCampaignsCardView.swift */; }; 0CDEC40D2A2FAF0500BB3A91 /* DashboardBlazeCampaignsCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CDEC40B2A2FAF0500BB3A91 /* DashboardBlazeCampaignsCardView.swift */; }; 0CED95602A460F4B0020F420 /* DebugFeatureFlagsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CED955F2A460F4B0020F420 /* DebugFeatureFlagsView.swift */; }; @@ -1363,7 +1365,6 @@ 5DB4683B18A2E718004A89A9 /* LocationService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DB4683A18A2E718004A89A9 /* LocationService.m */; }; 5DB767411588F64D00EBE36C /* postPreview.html in Resources */ = {isa = PBXBuildFile; fileRef = 5DB767401588F64D00EBE36C /* postPreview.html */; }; 5DBCD9D518F35D7500B32229 /* ReaderTopicService.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DBCD9D418F35D7500B32229 /* ReaderTopicService.m */; }; - 5DBFC8A91A9BE07B00E00DE4 /* Posts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5DBFC8A81A9BE07B00E00DE4 /* Posts.storyboard */; }; 5DED0E181B432E0400431FCD /* SourcePostAttribution.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DED0E171B432E0400431FCD /* SourcePostAttribution.m */; }; 5DF7F7741B22337C003A05C8 /* WordPress-30-31.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7F7731B22337C003A05C8 /* WordPress-30-31.xcmappingmodel */; }; 5DF7F7781B223916003A05C8 /* PostToPost30To31.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7F7771B223916003A05C8 /* PostToPost30To31.m */; }; @@ -3946,7 +3947,6 @@ FABB1FC82602FC2C00C8785C /* EpilogueSectionHeaderFooter.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98579BC6203DD86E004086E4 /* EpilogueSectionHeaderFooter.xib */; }; FABB1FC92602FC2C00C8785C /* reader.css in Resources */ = {isa = PBXBuildFile; fileRef = 8B64B4B1247EC3A2009A1229 /* reader.css */; }; FABB1FCC2602FC2C00C8785C /* SiteStatsTableHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98F537A822496D0D00B334F9 /* SiteStatsTableHeaderView.xib */; }; - FABB1FCD2602FC2C00C8785C /* Posts.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5DBFC8A81A9BE07B00E00DE4 /* Posts.storyboard */; }; FABB1FCE2602FC2C00C8785C /* StatsChildRowsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 98B11B8A2216536C00B7F2D7 /* StatsChildRowsView.xib */; }; FABB1FD02602FC2C00C8785C /* xhtml1-transitional.dtd in Resources */ = {isa = PBXBuildFile; fileRef = 2FAE97070E33B21600CA8540 /* xhtml1-transitional.dtd */; }; FABB1FD22602FC2C00C8785C /* RestoreStatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA1A55FE25A6F07F0033967D /* RestoreStatusView.xib */; }; @@ -6121,6 +6121,7 @@ 0CD223DE2AA8ADFD002BD761 /* DashboardQuickActionsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardQuickActionsViewModel.swift; sourceTree = ""; }; 0CD382822A4B699E00612173 /* DashboardBlazeCardCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardBlazeCardCellViewModel.swift; sourceTree = ""; }; 0CD382852A4B6FCE00612173 /* DashboardBlazeCardCellViewModelTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardBlazeCardCellViewModelTest.swift; sourceTree = ""; }; + 0CD9CC9E2AD73A560044A33C /* PostSearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostSearchViewController.swift; sourceTree = ""; }; 0CDEC40B2A2FAF0500BB3A91 /* DashboardBlazeCampaignsCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashboardBlazeCampaignsCardView.swift; sourceTree = ""; }; 0CED955F2A460F4B0020F420 /* DebugFeatureFlagsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFeatureFlagsView.swift; sourceTree = ""; }; 0CF7D6C22ABB753A006D1E89 /* MediaImageServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaImageServiceTests.swift; sourceTree = ""; }; @@ -6992,7 +6993,6 @@ 5DB767401588F64D00EBE36C /* postPreview.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = postPreview.html; path = Resources/HTML/postPreview.html; sourceTree = ""; }; 5DBCD9D318F35D7500B32229 /* ReaderTopicService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderTopicService.h; sourceTree = ""; }; 5DBCD9D418F35D7500B32229 /* ReaderTopicService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderTopicService.m; sourceTree = ""; }; - 5DBFC8A81A9BE07B00E00DE4 /* Posts.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Posts.storyboard; sourceTree = ""; }; 5DBFC8AA1A9C0EEF00E00DE4 /* WPScrollableViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WPScrollableViewController.h; sourceTree = ""; }; 5DE471B71B4C710E00665C44 /* ReaderPostContentProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReaderPostContentProvider.h; sourceTree = ""; }; 5DE8A0401912D95B00B2FF59 /* ReaderPostServiceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderPostServiceTest.m; sourceTree = ""; }; @@ -12442,6 +12442,7 @@ isa = PBXGroup; children = ( 591232681CCEAA5100B86207 /* AbstractPostListViewController.swift */, + 0CD9CC9E2AD73A560044A33C /* PostSearchViewController.swift */, 590E873A1CB8205700D1B734 /* PostListViewController.swift */, E684383D221F535900752258 /* LoadMoreCounter.swift */, ); @@ -14771,7 +14772,6 @@ 32CA6EBF2390C61F00B51347 /* PostListEditorPresenter.swift */, 430693731DD25F31009398A2 /* PostPost.storyboard */, 43D54D121DCAA070007F575F /* PostPostViewController.swift */, - 5DBFC8A81A9BE07B00E00DE4 /* Posts.storyboard */, 5D62BAD818AAAE9B0044E5F7 /* PostSettingsViewController_Internal.h */, ACBAB5FC0E121C7300F38795 /* PostSettingsViewController.h */, ACBAB5FD0E121C7300F38795 /* PostSettingsViewController.m */, @@ -19018,7 +19018,6 @@ 1761F17726209AEE000815EF /* wordpress-dark-icon-app-76x76.png in Resources */, 08BA4BC7298A9AD500015BD2 /* JetpackInstallPluginLogoAnimation_rtl.json in Resources */, 98F537A922496D0D00B334F9 /* SiteStatsTableHeaderView.xib in Resources */, - 5DBFC8A91A9BE07B00E00DE4 /* Posts.storyboard in Resources */, 1761F18426209AEE000815EF /* jetpack-green-icon-app-76x76@2x.png in Resources */, 98B11B8B2216536C00B7F2D7 /* StatsChildRowsView.xib in Resources */, 2FAE970C0E33B21600CA8540 /* xhtml1-transitional.dtd in Resources */, @@ -19561,7 +19560,6 @@ 01A8508C2A8A126400BD8A97 /* support_chat_widget.css in Resources */, FABB1FCC2602FC2C00C8785C /* SiteStatsTableHeaderView.xib in Resources */, F41E4EEF28F247D3001880C6 /* white-on-green-icon-app-60@2x.png in Resources */, - FABB1FCD2602FC2C00C8785C /* Posts.storyboard in Resources */, F41E4EB628F225DB001880C6 /* stroke-dark-icon-app-83.5@2x.png in Resources */, FABB1FCE2602FC2C00C8785C /* StatsChildRowsView.xib in Resources */, F41E4EEE28F247D3001880C6 /* white-on-green-icon-app-76.png in Resources */, @@ -22327,6 +22325,7 @@ 98BC522427F6245700D6E8C2 /* BloggingPromptsFeatureIntroduction.swift in Sources */, 8BF1C81A27BC00AF00F1C203 /* BlogDashboardCardFrameView.swift in Sources */, E1209FA41BB4978B00D69778 /* PeopleService.swift in Sources */, + 0CD9CC9F2AD73A560044A33C /* PostSearchViewController.swift in Sources */, 984B139421F66B2D0004B6A2 /* StatsPeriodStore.swift in Sources */, DC772AF1282009BA00664C02 /* InsightsLineChart.swift in Sources */, E13A8C9B1C3E6EF2005BB1C1 /* ImmuTable+WordPress.swift in Sources */, @@ -25246,6 +25245,7 @@ FABB25652602FC2C00C8785C /* MediaProgressCoordinator.swift in Sources */, FABB25662602FC2C00C8785C /* NSMutableAttributedString+Helpers.swift in Sources */, FABB25672602FC2C00C8785C /* PushNotificationsManager.swift in Sources */, + 0CD9CCA02AD73A560044A33C /* PostSearchViewController.swift in Sources */, FABB25682602FC2C00C8785C /* StatsInsightsStore.swift in Sources */, FABB25692602FC2C00C8785C /* MenuItemPagesViewController.m in Sources */, 4A9314E52979FA4700360232 /* PostCategory+Creation.swift in Sources */,