From 261ad101e7feb6798e137d61ddeb126140c8b05d Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 12 Feb 2024 17:08:15 -0500 Subject: [PATCH 01/14] Reimplement PrepublishingHeaderView --- .../ViewRelated/Post/PostEditor+Publish.swift | 17 +- .../PrepublishingHeaderView.swift | 147 ++++++++---------- .../PrepublishingHeaderView.xib | 140 ----------------- .../PrepublishingViewController.swift | 107 ++++++++----- WordPress/WordPress.xcodeproj/project.pbxproj | 38 ++--- .../PrepublishingHeaderViewTests.swift | 27 ---- 6 files changed, 158 insertions(+), 318 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.xib delete mode 100644 WordPress/WordPressTest/PrepublishingHeaderViewTests.swift diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift index efc879d1a565..ec717deec375 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift @@ -250,12 +250,19 @@ extension PublishingEditor { let isTitleDisplayed = prepublishingIdentifiers.contains { $0 == .title } let shouldDisplayPortrait = WPDeviceIdentification.isiPhone() && isTitleDisplayed let prepublishingNavigationController = PrepublishingNavigationController(rootViewController: prepublishing, shouldDisplayPortrait: shouldDisplayPortrait) - let bottomSheet = BottomSheetViewController(childViewController: prepublishingNavigationController, customHeaderSpacing: 0) - if let sourceView = prepublishingSourceView { - bottomSheet.show(from: self, sourceView: sourceView) - } else { - bottomSheet.show(from: self.topmostPresentedViewController) + if let sheetController = prepublishingNavigationController.sheetPresentationController { + if #available(iOS 16, *) { + sheetController.detents = [ + .custom(resolver: { context in + return 520 + }), + .large() + ] + } + } else if let popoverController = prepublishingNavigationController.popoverPresentationController { + // TODO: complete on iPad (preferredContentSize) } + topmostPresentedViewController.present(prepublishingNavigationController, animated: true) } /// Displays a publish confirmation alert with two options: "Keep Editing" and String for Action. diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift index e5969af5db3e..01be360a7cda 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift @@ -1,97 +1,82 @@ import UIKit -import Gridicons -protocol PrepublishingHeaderViewDelegate: AnyObject { - func closeButtonTapped() -} - -class PrepublishingHeaderView: UITableViewHeaderFooterView, NibLoadable { - - @IBOutlet weak var blogImageView: UIImageView! - @IBOutlet weak var publishingToLabel: UILabel! - @IBOutlet weak var blogTitleLabel: UILabel! - @IBOutlet weak var closeButtonView: UIView! - @IBOutlet weak var leadingConstraint: NSLayoutConstraint! - @IBOutlet weak var closeButton: UIButton! - @IBOutlet weak var separator: UIView! - - weak var delegate: PrepublishingHeaderViewDelegate? - - func configure(_ blog: Blog) { - blogImageView.downloadSiteIcon(for: blog) - blogTitleLabel.text = blog.title - } - - // MARK: - Close button - - func toggleCloseButton(visible: Bool) { - closeButtonView.layer.opacity = visible ? 1 : 0 - closeButtonView.isHidden = visible ? false : true - leadingConstraint.constant = visible ? 0 : Constants.leftRightInset - layoutIfNeeded() - } - - @IBAction func closeButtonTapped(_ sender: Any) { - delegate?.closeButtonTapped() - } +final class PrepublishingHeaderView: UIView { + private let blogImageView = UIImageView() + private let publishingToLabel = UILabel() + private let blogTitleLabel = UILabel() - // MARK: - Style + let closeButton = UIButton(type: .system) + let separator = UIView() - override func awakeFromNib() { - super.awakeFromNib() - configureBackgroundView() - configureBackButton() - configurePublishingToLabel() - configureBlogTitleLabel() - configureBlogImage() - configureSeparator() - } - - override func prepareForReuse() { - super.prepareForReuse() + override init(frame: CGRect) { + super.init(frame: frame) - self.delegate = nil - } + blogImageView.layer.masksToBounds = true + blogImageView.layer.cornerRadius = 6 - private func configureBackgroundView() { - backgroundView = UIView() - backgroundView?.backgroundColor = .basicBackground - } + publishingToLabel.text = Strings.publishingTo.uppercased() + publishingToLabel.font = WPStyleGuide.fontForTextStyle(.caption1) + publishingToLabel.textColor = .secondaryLabel - private func configureBackButton() { - closeButtonView.isHidden = true - closeButton.setImage(.gridicon(.cross, size: Constants.backButtonSize), for: .normal) - closeButton.accessibilityLabel = Constants.close - closeButton.accessibilityHint = Constants.doubleTapToDismiss + blogTitleLabel.font = WPStyleGuide.fontForTextStyle(.headline) - // Only show close button for accessibility purposes - toggleCloseButton(visible: UIAccessibility.isVoiceOverRunning) - } - - private func configurePublishingToLabel() { - publishingToLabel.text = publishingToLabel.text?.uppercased() - publishingToLabel.font = WPStyleGuide.TableViewHeaderDetailView.titleFont - publishingToLabel.textColor = WPStyleGuide.TableViewHeaderDetailView.titleColor - } + closeButton.configuration = { + var configuration = UIButton.Configuration.plain() + configuration.image = UIImage(systemName: "xmark.circle.fill") + configuration.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 10, bottom: 10, trailing: 10) + configuration.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(paletteColors: [.secondaryLabel, .secondarySystemFill]) + .applying(UIImage.SymbolConfiguration(font: WPStyleGuide.fontForTextStyle(.headline, fontWeight: .semibold))) + return configuration + }() + closeButton.accessibilityLabel = Strings.close - private func configureBlogImage() { - blogImageView.layer.cornerRadius = Constants.imageRadius - blogImageView.clipsToBounds = true + WPStyleGuide.applyBorderStyle(separator) + separator.alpha = 0 + + NSLayoutConstraint.activate([ + blogImageView.widthAnchor.constraint(equalToConstant: 44), + blogImageView.heightAnchor.constraint(equalToConstant: 44), + ]) + + let labelsStackView = UIStackView(arrangedSubviews: [publishingToLabel, blogTitleLabel]) + labelsStackView.axis = .vertical + labelsStackView.alignment = .leading + + let stackView = UIStackView(arrangedSubviews: [blogImageView, labelsStackView]) + stackView.translatesAutoresizingMaskIntoConstraints = false + stackView.alignment = .center + stackView.spacing = 12 + addSubview(stackView) + pinSubviewToAllEdges(stackView, insets: UIEdgeInsets(allEdges: 16)) + + addSubview(separator) + separator.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + separator.leadingAnchor.constraint(equalTo: leadingAnchor), + separator.trailingAnchor.constraint(equalTo: trailingAnchor), + separator.bottomAnchor.constraint(equalTo: bottomAnchor) + ]) + + addSubview(closeButton) + closeButton.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + closeButton.trailingAnchor.constraint(equalTo: trailingAnchor), + closeButton.topAnchor.constraint(equalTo: topAnchor), + blogTitleLabel.trailingAnchor.constraint(lessThanOrEqualTo: closeButton.leadingAnchor) + ]) } - private func configureBlogTitleLabel() { - WPStyleGuide.applyPostTitleStyle(blogTitleLabel) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } - private func configureSeparator() { - WPStyleGuide.applyBorderStyle(separator) + func configure(_ blog: Blog) { + blogImageView.downloadSiteIcon(for: blog) + blogTitleLabel.text = blog.title } +} - private enum Constants { - static let backButtonSize = CGSize(width: 28, height: 28) - static let imageRadius: CGFloat = 4 - static let leftRightInset: CGFloat = 16 - static let close = NSLocalizedString("Close", comment: "Voiceover accessibility label informing the user that this button dismiss the current view") - static let doubleTapToDismiss = NSLocalizedString("Double tap to dismiss", comment: "Voiceover accessibility hint informing the user they can double tap a modal alert to dismiss it") - } +private enum Strings { + static let close = NSLocalizedString("prepublishingSheet.pubishingTo", value: "Close", comment: "Voiceover accessibility label informing the user that this button dismiss the current view") + static let publishingTo = NSLocalizedString("prepublishingSheet.pubishingTo", value: "Publishing to", comment: "Label in the header in the pre-publishing sheet") } diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.xib b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.xib deleted file mode 100644 index a0b33b8abbd5..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.xib +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 5eb4f75a0ffb..fb356bc75cf4 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -31,7 +31,9 @@ enum PrepublishingIdentifier { } } -class PrepublishingViewController: UITableViewController { +// TODO: private + final +// TODO: add deselect +class PrepublishingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let post: Post let identifiers: [PrepublishingIdentifier] let coreDataStack: CoreDataStackSwift @@ -55,6 +57,7 @@ class PrepublishingViewController: UITableViewController { return PublishSettingsViewModel(post: post) }() + #warning("TODO: remove") private var presentedVC: DrawerPresentationController? { return (navigationController as? PrepublishingNavigationController)?.presentedVC } @@ -71,6 +74,10 @@ class PrepublishingViewController: UITableViewController { private var didTapPublish = false + private let headerView = PrepublishingHeaderView() + let tableView = UITableView(frame: .zero, style: .plain) + + // TODO: make private let publishButton: NUXButton = { let nuxButton = NUXButton() nuxButton.isPrimary = true @@ -124,10 +131,28 @@ class PrepublishingViewController: UITableViewController { refreshOptions() + configureHeader() + configureTableView() + configureKeyboardToggle() + title = "" - let nib = UINib(nibName: "PrepublishingHeaderView", bundle: nil) - tableView.register(nib, forHeaderFooterViewReuseIdentifier: Constants.headerReuseIdentifier) + // TODO: cleanup + let footer = UIView() + footer.addSubview(publishButton) + publishButton.translatesAutoresizingMaskIntoConstraints = false + footer.pinSubviewToAllEdges(publishButton, insets: Constants.nuxButtonInsets) + + let stackView = UIStackView(arrangedSubviews: [ + headerView, + tableView, + footer + ]) + stackView.axis = .vertical + + view.addSubview(stackView) + stackView.translatesAutoresizingMaskIntoConstraints = false + view.pinSubviewToSafeArea(stackView) setupPublishButton() setupFooterSeparator() @@ -135,7 +160,21 @@ class PrepublishingViewController: UITableViewController { updatePublishButtonLabel() announcePublishButton() - configureKeyboardToggle() + // TODO: check dark mode + view.backgroundColor = .systemBackground + } + + private func configureHeader() { + headerView.closeButton.addAction(.init(handler: { [weak self] _ in + self?.presentingViewController?.dismiss(animated: true) + }), for: .touchUpInside) + headerView.configure(post.blog) + } + + private func configureTableView() { + tableView.dataSource = self + tableView.delegate = self + tableView.rowHeight = UITableView.automaticDimension } /// Toggles `keyboardShown` as the keyboard notifications come in @@ -176,30 +215,13 @@ class PrepublishingViewController: UITableViewController { } } - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { - guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: Constants.headerReuseIdentifier) as? PrepublishingHeaderView else { - return nil - } - - header.delegate = self - header.configure(post.blog) + // MARK: - UITableViewDataSource - return header + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + options.count } - override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { - return UITableView.automaticDimension - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return options.count - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let option = options[indexPath.row] @@ -258,7 +280,9 @@ class PrepublishingViewController: UITableViewController { } } - override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + // MARK: - UITableViewDelegate + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { switch options[indexPath.row].id { case .tags: didTapTagCell() @@ -275,6 +299,12 @@ class PrepublishingViewController: UITableViewController { } } + func scrollViewDidScroll(_ scrollView: UIScrollView) { + headerView.separator.alpha = max(0, min(1, scrollView.contentOffset.y / 60)) + } + + // MARK: – Misc + func reloadData() { refreshOptions() tableView.reloadData() @@ -397,13 +427,20 @@ class PrepublishingViewController: UITableViewController { // MARK: - Publish Button + // TODO: cleanuo private func setupPublishButton() { - let footer = UIView(frame: Constants.footerFrame) + return () + + let footer = UIView() footer.addSubview(publishButton) - footer.pinSubviewToSafeArea(publishButton, insets: Constants.nuxButtonInsets) publishButton.translatesAutoresizingMaskIntoConstraints = false - tableView.tableFooterView = footer - publishButton.addTarget(self, action: #selector(publish(_:)), for: .touchUpInside) + footer.pinSubviewToSafeArea(publishButton, insets: Constants.nuxButtonInsets) + + view.addSubview(footer) + footer.translatesAutoresizingMaskIntoConstraints = false + view.pinSubviewToSafeArea(footer, insets: .zero) + + publishButton.addTarget(self, action: #selector(publish), for: .touchUpInside) updatePublishButtonLabel() } @@ -480,7 +517,6 @@ class PrepublishingViewController: UITableViewController { fileprivate enum Constants { static let reuseIdentifier = "wpTableViewCell" - static let headerReuseIdentifier = "wpTableViewHeader" static let textFieldReuseIdentifier = "wpTextFieldCell" static let nuxButtonInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) static let cellMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) @@ -494,12 +530,7 @@ class PrepublishingViewController: UITableViewController { } } -extension PrepublishingViewController: PrepublishingHeaderViewDelegate { - func closeButtonTapped() { - dismiss(animated: true) - } -} - +// TODO: check this extension PrepublishingViewController: PrepublishingDismissible { func handleDismiss() { defer { completion(.dismissed) } @@ -538,12 +569,14 @@ extension PrepublishingViewController: PostCategoriesViewControllerDelegate { } } +#warning("TODO: remove") extension Set { var array: [Element] { return Array(self) } } +#warning("TODO: remove") // MARK: - DrawerPresentable extension PrepublishingViewController: DrawerPresentable { var allowsUserTransition: Bool { diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 52f032dd5233..cb485bc6e21f 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2227,7 +2227,6 @@ 85F8E19D1B018698000859BB /* PushAuthenticationServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85F8E19C1B018698000859BB /* PushAuthenticationServiceTests.swift */; }; 8B05D29123A9417E0063B9AA /* WPMediaEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B05D29023A9417E0063B9AA /* WPMediaEditor.swift */; }; 8B05D29323AA572A0063B9AA /* GutenbergMediaEditorImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B05D29223AA572A0063B9AA /* GutenbergMediaEditorImage.swift */; }; - 8B0732E7242B9C5200E7FBD3 /* PrepublishingHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B0732E6242B9C5200E7FBD3 /* PrepublishingHeaderView.xib */; }; 8B0732E9242BA1F000E7FBD3 /* PrepublishingHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */; }; 8B0732F0242BF7E800E7FBD3 /* Blog+Title.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */; }; 8B0732F3242BF99B00E7FBD3 /* PrepublishingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */; }; @@ -2340,7 +2339,6 @@ 8BDA5A74247C5EAA00AB124C /* ReaderDetailCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BDA5A73247C5EAA00AB124C /* ReaderDetailCoordinatorTests.swift */; }; 8BDA5A75247C63F300AB124C /* ReaderDetailCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BDA5A71247C5E5800AB124C /* ReaderDetailCoordinator.swift */; }; 8BDC4C39249BA5CA00DE0A2D /* ReaderCSS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BDC4C38249BA5CA00DE0A2D /* ReaderCSS.swift */; }; - 8BE69512243E674300FF492F /* PrepublishingHeaderViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BE69511243E674300FF492F /* PrepublishingHeaderViewTests.swift */; }; 8BE6F92A27EE26D30008BDC7 /* BlogDashboardPostCardGhostCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8BE6F92927EE26D30008BDC7 /* BlogDashboardPostCardGhostCell.xib */; }; 8BE6F92C27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BE6F92B27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift */; }; 8BE6F92D27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8BE6F92B27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift */; }; @@ -4054,7 +4052,6 @@ FABB1FB92602FC2C00C8785C /* RestoreStatusFailedView.xib in Resources */ = {isa = PBXBuildFile; fileRef = FA1CEAD325CA9C40005E7038 /* RestoreStatusFailedView.xib */; }; FABB1FBA2602FC2C00C8785C /* NoteBlockHeaderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B5C66B6F1ACF06CA00F68370 /* NoteBlockHeaderTableViewCell.xib */; }; FABB1FBB2602FC2C00C8785C /* CollapsableHeaderCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 469CE07024BCFB04003BDC8B /* CollapsableHeaderCollectionViewCell.xib */; }; - FABB1FBC2602FC2C00C8785C /* PrepublishingHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B0732E6242B9C5200E7FBD3 /* PrepublishingHeaderView.xib */; }; FABB1FBF2602FC2C00C8785C /* WPTableViewActivityCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5D6C4AF51B603CA3005E3C43 /* WPTableViewActivityCell.xib */; }; FABB1FC12602FC2C00C8785C /* defaultPostTemplate.html in Resources */ = {isa = PBXBuildFile; fileRef = A01C55470E25E0D000D411F2 /* defaultPostTemplate.html */; }; FABB1FC32602FC2C00C8785C /* defaultPostTemplate_old.html in Resources */ = {isa = PBXBuildFile; fileRef = 2FAE97040E33B21600CA8540 /* defaultPostTemplate_old.html */; }; @@ -7578,7 +7575,6 @@ 8A21014FBE43ADE551F4ECB4 /* Pods-JetpackIntents.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JetpackIntents.release-alpha.xcconfig"; path = "../Pods/Target Support Files/Pods-JetpackIntents/Pods-JetpackIntents.release-alpha.xcconfig"; sourceTree = ""; }; 8B05D29023A9417E0063B9AA /* WPMediaEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WPMediaEditor.swift; sourceTree = ""; }; 8B05D29223AA572A0063B9AA /* GutenbergMediaEditorImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GutenbergMediaEditorImage.swift; sourceTree = ""; }; - 8B0732E6242B9C5200E7FBD3 /* PrepublishingHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PrepublishingHeaderView.xib; sourceTree = ""; }; 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepublishingHeaderView.swift; sourceTree = ""; }; 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Blog+Title.swift"; sourceTree = ""; }; 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepublishingNavigationController.swift; sourceTree = ""; }; @@ -7665,7 +7661,6 @@ 8BDA5A71247C5E5800AB124C /* ReaderDetailCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderDetailCoordinator.swift; sourceTree = ""; }; 8BDA5A73247C5EAA00AB124C /* ReaderDetailCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderDetailCoordinatorTests.swift; sourceTree = ""; }; 8BDC4C38249BA5CA00DE0A2D /* ReaderCSS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderCSS.swift; sourceTree = ""; }; - 8BE69511243E674300FF492F /* PrepublishingHeaderViewTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PrepublishingHeaderViewTests.swift; path = WordPressTest/PrepublishingHeaderViewTests.swift; sourceTree = SOURCE_ROOT; }; 8BE6F92927EE26D30008BDC7 /* BlogDashboardPostCardGhostCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = BlogDashboardPostCardGhostCell.xib; sourceTree = ""; }; 8BE6F92B27EE27DB0008BDC7 /* BlogDashboardPostCardGhostCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardPostCardGhostCell.swift; sourceTree = ""; }; 8BE7C84023466927006EDE70 /* I18n.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = I18n.swift; sourceTree = ""; }; @@ -10845,7 +10840,7 @@ path = Classes; sourceTree = ""; }; - 29B97314FDCFA39411CA2CEA = { + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { isa = PBXGroup; children = ( 3F20FDF3276BF21000DA3CAD /* Packages */, @@ -12438,7 +12433,6 @@ 59ECF8791CB705EB00E68F25 /* Posts */ = { isa = PBXGroup; children = ( - 8BE69514243E676C00FF492F /* Prepublishing Nudges */, 59ECF87A1CB7061D00E68F25 /* PostSharingControllerTests.swift */, F18B43771F849F580089B817 /* PostAttachmentTests.swift */, 8B6BD54F24293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift */, @@ -13927,7 +13921,6 @@ 8B0732EA242BEF1900E7FBD3 /* Prepublishing Nudge */ = { isa = PBXGroup; children = ( - 8B0732E6242B9C5200E7FBD3 /* PrepublishingHeaderView.xib */, 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */, 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */, 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */, @@ -14136,14 +14129,6 @@ path = Views; sourceTree = ""; }; - 8BE69514243E676C00FF492F /* Prepublishing Nudges */ = { - isa = PBXGroup; - children = ( - 8BE69511243E674300FF492F /* PrepublishingHeaderViewTests.swift */, - ); - name = "Prepublishing Nudges"; - sourceTree = ""; - }; 8BE6F92827EE26AF0008BDC7 /* Views */ = { isa = PBXGroup; children = ( @@ -19224,13 +19209,13 @@ bg, sk, ); - mainGroup = 29B97314FDCFA39411CA2CEA; + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; packageReferences = ( 3FF1442E266F3C2400138163 /* XCRemoteSwiftPackageReference "ScreenObject" */, 3FC2C33B26C4CF0A00C6D98F /* XCRemoteSwiftPackageReference "XCUITestHelpers" */, 17A8858B2757B97F0071FCA3 /* XCRemoteSwiftPackageReference "AutomatticAbout-swift" */, 3F3B23C02858A1B300CACE60 /* XCRemoteSwiftPackageReference "test-collector-swift" */, - 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios.git" */, + 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios" */, 3F338B6F289BD3040014ADC5 /* XCRemoteSwiftPackageReference "Nimble" */, 0CD9FB852AFA71B9009D9C7A /* XCRemoteSwiftPackageReference "Charts" */, ); @@ -19305,7 +19290,6 @@ FE39C135269C37C900EFB827 /* ListTableViewCell.xib in Resources */, 469CE07224BCFB04003BDC8B /* CollapsableHeaderCollectionViewCell.xib in Resources */, 17222D9B261DDDF90047B163 /* black-icon-app-76x76.png in Resources */, - 8B0732E7242B9C5200E7FBD3 /* PrepublishingHeaderView.xib in Resources */, DC772B0828201F5300664C02 /* ViewsVisitorsLineChartCell.xib in Resources */, 5D6C4AF61B603CA3005E3C43 /* WPTableViewActivityCell.xib in Resources */, A01C55480E25E0D000D411F2 /* defaultPostTemplate.html in Resources */, @@ -19836,7 +19820,6 @@ FABB1FBB2602FC2C00C8785C /* CollapsableHeaderCollectionViewCell.xib in Resources */, FE43DAB226DFAD1C00CFF595 /* CommentContentTableViewCell.xib in Resources */, C7234A452832C2BA0045C63F /* QRLoginScanningViewController.xib in Resources */, - FABB1FBC2602FC2C00C8785C /* PrepublishingHeaderView.xib in Resources */, FABB1FBF2602FC2C00C8785C /* WPTableViewActivityCell.xib in Resources */, FABB1FC12602FC2C00C8785C /* defaultPostTemplate.html in Resources */, FABB1FC32602FC2C00C8785C /* defaultPostTemplate_old.html in Resources */, @@ -20811,11 +20794,11 @@ files = ( ); inputPaths = ( - "$SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.inputs.xcfilelist", + $SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.inputs.xcfilelist, ); name = "Copy Gutenberg JS"; outputFileListPaths = ( - "$SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.outputs.xcfilelist", + $SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.outputs.xcfilelist, ); outputPaths = ( "", @@ -21004,13 +20987,13 @@ files = ( ); inputFileListPaths = ( - "$SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.inputs.xcfilelist", + $SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.inputs.xcfilelist, ); inputPaths = ( ); name = "Copy Gutenberg JS"; outputFileListPaths = ( - "$SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.outputs.xcfilelist", + $SRCROOT/../Scripts/BuildPhases/CopyGutenbergJS.outputs.xcfilelist, ); outputPaths = ( ); @@ -23724,7 +23707,6 @@ E6B9B8AF1B94FA1C0001B92F /* ReaderStreamViewControllerTests.swift in Sources */, 01E2580E2ACDC88100F09666 /* PlanWizardContentViewModelTests.swift in Sources */, 4629E4232440C8160002E15C /* GutenbergCoverUploadProcessorTests.swift in Sources */, - 8BE69512243E674300FF492F /* PrepublishingHeaderViewTests.swift in Sources */, FAF0FAAC2AA094C0004C3228 /* NoSiteViewModelTests.swift in Sources */, 02BE5CC02281B53F00E351BA /* RegisterDomainDetailsViewModelLoadingStateTests.swift in Sources */, FEFA263E26C58427009CCB7E /* ShareAppTextActivityItemSourceTests.swift in Sources */, @@ -30454,7 +30436,7 @@ minimumVersion = 0.3.0; }; }; - 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios.git" */ = { + 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/airbnb/lottie-ios.git"; requirement = { @@ -30543,12 +30525,12 @@ }; 3F411B6E28987E3F002513AE /* Lottie */ = { isa = XCSwiftPackageProductDependency; - package = 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios.git" */; + package = 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios" */; productName = Lottie; }; 3F44DD57289C379C006334CD /* Lottie */ = { isa = XCSwiftPackageProductDependency; - package = 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios.git" */; + package = 3F411B6D28987E3F002513AE /* XCRemoteSwiftPackageReference "lottie-ios" */; productName = Lottie; }; 3F9F23242B0AE1AC00B56061 /* JetpackStatsWidgetsCore */ = { diff --git a/WordPress/WordPressTest/PrepublishingHeaderViewTests.swift b/WordPress/WordPressTest/PrepublishingHeaderViewTests.swift deleted file mode 100644 index 1e9abaeca959..000000000000 --- a/WordPress/WordPressTest/PrepublishingHeaderViewTests.swift +++ /dev/null @@ -1,27 +0,0 @@ -import UIKit -import Nimble -import XCTest - -@testable import WordPress - -class PrepublishingHeaderViewTests: XCTestCase { - - func testShareControllerCreated() { - let prepublishingHeaderView = PrepublishingHeaderView.loadFromNib() - let delegateMock = PrepublishingHeaderViewDelegateMock() - prepublishingHeaderView.delegate = delegateMock - - prepublishingHeaderView.closeButton.sendActions(for: .touchUpInside) - - expect(delegateMock.didCallCloseButtonTapped).to(beTrue()) - } - -} - -class PrepublishingHeaderViewDelegateMock: PrepublishingHeaderViewDelegate { - var didCallCloseButtonTapped = false - - func closeButtonTapped() { - didCallCloseButtonTapped = true - } -} From 602482d9b5302e194529e5930eba069247a01e7f Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 12 Feb 2024 17:32:10 -0500 Subject: [PATCH 02/14] Minor improvements PrepublishingViewController.swift --- .../People/InvitePersonViewController.swift | 2 +- .../ViewRelated/Post/PostEditor+Publish.swift | 9 ++- .../PrepublishingHeaderView.swift | 5 +- ...blishingViewController+JetpackSocial.swift | 22 +++--- .../PrepublishingViewController.swift | 73 ++++++++----------- WordPress/WordPress.xcodeproj/project.pbxproj | 4 - ...epublishingNudgesViewControllerTests.swift | 45 ------------ 7 files changed, 56 insertions(+), 104 deletions(-) delete mode 100644 WordPress/WordPressTest/PrepublishingNudgesViewControllerTests.swift diff --git a/WordPress/Classes/ViewRelated/People/InvitePersonViewController.swift b/WordPress/Classes/ViewRelated/People/InvitePersonViewController.swift index 9f17506a1b00..0c5c676e20e9 100644 --- a/WordPress/Classes/ViewRelated/People/InvitePersonViewController.swift +++ b/WordPress/Classes/ViewRelated/People/InvitePersonViewController.swift @@ -92,7 +92,7 @@ class InvitePersonViewController: UITableViewController { private var sortedInviteLinks: [InviteLinks] { guard - let links = blog.inviteLinks?.array as? [InviteLinks] + let links = Array(blog.inviteLinks ?? []) as? [InviteLinks] else { return [] } diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift index ec717deec375..443618608da4 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift @@ -250,14 +250,21 @@ extension PublishingEditor { let isTitleDisplayed = prepublishingIdentifiers.contains { $0 == .title } let shouldDisplayPortrait = WPDeviceIdentification.isiPhone() && isTitleDisplayed let prepublishingNavigationController = PrepublishingNavigationController(rootViewController: prepublishing, shouldDisplayPortrait: shouldDisplayPortrait) + + // TODO: make it work on iPad + // TODO: make it work in other places + // TODO: compute size dynamically if let sheetController = prepublishingNavigationController.sheetPresentationController { if #available(iOS 16, *) { sheetController.detents = [ .custom(resolver: { context in - return 520 + return 540 }), .large() ] + sheetController.prefersGrabberVisible = true + sheetController.preferredCornerRadius = 16 + prepublishingNavigationController.additionalSafeAreaInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) } } else if let popoverController = prepublishingNavigationController.popoverPresentationController { // TODO: complete on iPad (preferredContentSize) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift index 01be360a7cda..28b6dd20f8c1 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift @@ -13,6 +13,7 @@ final class PrepublishingHeaderView: UIView { blogImageView.layer.masksToBounds = true blogImageView.layer.cornerRadius = 6 + blogImageView.layer.cornerCurve = .continuous publishingToLabel.text = Strings.publishingTo.uppercased() publishingToLabel.font = WPStyleGuide.fontForTextStyle(.caption1) @@ -23,7 +24,7 @@ final class PrepublishingHeaderView: UIView { closeButton.configuration = { var configuration = UIButton.Configuration.plain() configuration.image = UIImage(systemName: "xmark.circle.fill") - configuration.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 10, bottom: 10, trailing: 10) + configuration.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 14, bottom: 14, trailing: 12) configuration.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(paletteColors: [.secondaryLabel, .secondarySystemFill]) .applying(UIImage.SymbolConfiguration(font: WPStyleGuide.fontForTextStyle(.headline, fontWeight: .semibold))) return configuration @@ -47,7 +48,7 @@ final class PrepublishingHeaderView: UIView { stackView.alignment = .center stackView.spacing = 12 addSubview(stackView) - pinSubviewToAllEdges(stackView, insets: UIEdgeInsets(allEdges: 16)) + pinSubviewToAllEdges(stackView, insets: UIEdgeInsets(top: 16, left: 20, bottom: 12, right: 20)) addSubview(separator) separator.translatesAutoresizingMaskIntoConstraints = false diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift index 6319c820e626..905fe741827e 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift @@ -1,3 +1,6 @@ +import UIKit +import SwiftUI + /// Encapsulates logic related to Jetpack Social in the pre-publishing sheet. /// extension PrepublishingViewController { @@ -109,15 +112,11 @@ private extension PrepublishingViewController { func configureAutoSharingView(for cell: UITableViewCell) { let viewModel = makeAutoSharingModel() let viewToEmbed = UIView.embedSwiftUIView(PrepublishingAutoSharingView(model: viewModel)) - cell.contentView.addSubview(viewToEmbed) - // Pin constraints to the cell's layoutMarginsGuide so that the content is properly aligned. - NSLayoutConstraint.activate([ - viewToEmbed.leadingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.leadingAnchor), - viewToEmbed.topAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.topAnchor), - viewToEmbed.bottomAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.bottomAnchor), - viewToEmbed.trailingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.trailingAnchor) - ]) + viewToEmbed.translatesAutoresizingMaskIntoConstraints = false + cell.selectionStyle = .default + cell.contentView.addSubview(viewToEmbed) + cell.contentView.pinSubviewToAllEdgeMargins(viewToEmbed) cell.accessoryType = .disclosureIndicator @@ -134,8 +133,10 @@ private extension PrepublishingViewController { return } + viewToEmbed.translatesAutoresizingMaskIntoConstraints = false + cell.selectionStyle = .none cell.contentView.addSubview(viewToEmbed) - cell.contentView.pinSubviewToSafeArea(viewToEmbed) + cell.contentView.pinSubviewToAllEdgeMargins(viewToEmbed) WPAnalytics.track(.jetpackSocialNoConnectionCardDisplayed, properties: ["source": Constants.trackingSource]) } @@ -143,10 +144,11 @@ private extension PrepublishingViewController { func makeNoConnectionViewModel() -> JetpackSocialNoConnectionViewModel { let context = post.managedObjectContext ?? coreDataStack.mainContext guard let services = try? PublicizeService.allSupportedServices(in: context) else { - return .init() + return .init(padding: EdgeInsets(.zero)) } return .init(services: services, + padding: EdgeInsets(.zero), preferredBackgroundColor: tableView.backgroundColor, onConnectTap: noConnectionConnectTapped(), onNotNowTap: noConnectionDismissTapped()) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index fb356bc75cf4..55d57df3dab0 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -3,18 +3,6 @@ import WordPressAuthenticator import Combine import WordPressUI -private struct PrepublishingOption { - let id: PrepublishingIdentifier - let title: String - let type: PrepublishingCellType -} - -private enum PrepublishingCellType { - case value - case textField - case customContainer -} - enum PrepublishingIdentifier { case title case schedule @@ -31,9 +19,9 @@ enum PrepublishingIdentifier { } } -// TODO: private + final -// TODO: add deselect -class PrepublishingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { +// TODO: Fix insets for "social" and "publish" +// TODO: Check if deinit works +final class PrepublishingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let post: Post let identifiers: [PrepublishingIdentifier] let coreDataStack: CoreDataStackSwift @@ -58,7 +46,7 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa }() #warning("TODO: remove") - private var presentedVC: DrawerPresentationController? { + var presentedVC: DrawerPresentationController? { return (navigationController as? PrepublishingNavigationController)?.presentedVC } @@ -76,6 +64,7 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa private let headerView = PrepublishingHeaderView() let tableView = UITableView(frame: .zero, style: .plain) + private let footerSeparator = UIView() // TODO: make private let publishButton: NUXButton = { @@ -143,9 +132,12 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa publishButton.translatesAutoresizingMaskIntoConstraints = false footer.pinSubviewToAllEdges(publishButton, insets: Constants.nuxButtonInsets) + WPStyleGuide.applyBorderStyle(footerSeparator) + let stackView = UIStackView(arrangedSubviews: [ headerView, tableView, + footerSeparator, footer ]) stackView.axis = .vertical @@ -191,13 +183,20 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() + // TODO: remove/reimplemnet? preferredContentSize = tableView.contentSize + footerSeparator.isHidden = tableView.contentSize.height < tableView.bounds.height } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(true, animated: animated) + if let indexPath = tableView.indexPathForSelectedRow { + tableView.deselectRow(at: indexPath, animated: true) + } + // Setting titleField first resonder alongside our transition to avoid layout issues. transitionCoordinator?.animateAlongsideTransition(in: nil, animation: { [weak self] _ in if self?.hasSelectedText == false { @@ -209,6 +208,7 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + let isPresentingAViewController = navigationController?.viewControllers.count ?? 0 > 1 if isPresentingAViewController { navigationController?.setNavigationBarHidden(false, animated: animated) @@ -222,15 +222,9 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let option = options[indexPath.row] - let cell = dequeueCell(for: option.type, indexPath: indexPath) - cell.preservesSuperviewLayoutMargins = false - cell.separatorInset = .zero - cell.layoutMargins = Constants.cellMargins - switch option.type { case .textField: if let cell = cell as? WPTextFieldTableViewCell { @@ -353,11 +347,11 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa } private func configureCategoriesCell(_ cell: WPTableViewCell) { - cell.detailTextLabel?.text = post.categories?.array.map { $0.categoryName }.joined(separator: ",") + cell.detailTextLabel?.text = Array(post.categories ?? []).map { $0.categoryName }.joined(separator: ",") } private func didTapCategoriesCell() { - let categoriesViewController = PostCategoriesViewController(blog: post.blog, currentSelection: post.categories?.array, selectionMode: .post) + let categoriesViewController = PostCategoriesViewController(blog: post.blog, currentSelection: Array(post.categories ?? []), selectionMode: .post) categoriesViewController.delegate = self categoriesViewController.onCategoriesChanged = { [weak self] in self?.presentedVC?.containerViewWillLayoutSubviews() @@ -519,8 +513,6 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa static let reuseIdentifier = "wpTableViewCell" static let textFieldReuseIdentifier = "wpTextFieldCell" static let nuxButtonInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) - static let cellMargins = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) - static let footerFrame = CGRect(x: 0, y: 0, width: 100, height: 80) static let publishNow = NSLocalizedString("Publish Now", comment: "Label for a button that publishes the post") static let scheduleNow = NSLocalizedString("Schedule Now", comment: "Label for the button that schedules the post") static let publishDateLabel = NSLocalizedString("Publish Date", comment: "Label for Publish date") @@ -530,6 +522,12 @@ class PrepublishingViewController: UIViewController, UITableViewDataSource, UITa } } +// TODO: Remove other ones +private enum Strings { + static let publish = NSLocalizedString("prepublishingSheet.publish", value: "Publish", comment: "Label for a button that publishes the post") + static let schedule = NSLocalizedString("prepublishingSheet.schedule", value: "Schedule", comment: "Label for a button that publishes the post") +} + // TODO: check this extension PrepublishingViewController: PrepublishingDismissible { func handleDismiss() { @@ -569,23 +567,16 @@ extension PrepublishingViewController: PostCategoriesViewControllerDelegate { } } -#warning("TODO: remove") -extension Set { - var array: [Element] { - return Array(self) - } +private struct PrepublishingOption { + let id: PrepublishingIdentifier + let title: String + let type: PrepublishingCellType } -#warning("TODO: remove") -// MARK: - DrawerPresentable -extension PrepublishingViewController: DrawerPresentable { - var allowsUserTransition: Bool { - return keyboardShown == false - } - - var collapsedHeight: DrawerHeight { - return .intrinsicHeight - } +private enum PrepublishingCellType { + case value + case textField + case customContainer } private extension PrepublishingOption { diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index cb485bc6e21f..55ef409e4a20 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2275,7 +2275,6 @@ 8B69F0E4255C2C3F006B1CEF /* ActivityListViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B69F0E3255C2C3F006B1CEF /* ActivityListViewModelTests.swift */; }; 8B69F100255C4870006B1CEF /* ActivityStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B69F0FF255C4870006B1CEF /* ActivityStoreTests.swift */; }; 8B69F19F255D67E7006B1CEF /* CalendarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B69F19E255D67E7006B1CEF /* CalendarViewController.swift */; }; - 8B6BD55024293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B6BD54F24293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift */; }; 8B6EA62323FDE50B004BA312 /* PostServiceUploadingList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B6EA62223FDE50B004BA312 /* PostServiceUploadingList.swift */; }; 8B749E7225AF522900023F03 /* JetpackCapabilitiesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B749E7125AF522900023F03 /* JetpackCapabilitiesService.swift */; }; 8B749E9025AF8D2E00023F03 /* JetpackCapabilitiesServiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B749E8F25AF8D2E00023F03 /* JetpackCapabilitiesServiceTests.swift */; }; @@ -7606,7 +7605,6 @@ 8B69F0E3255C2C3F006B1CEF /* ActivityListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityListViewModelTests.swift; sourceTree = ""; }; 8B69F0FF255C4870006B1CEF /* ActivityStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityStoreTests.swift; sourceTree = ""; }; 8B69F19E255D67E7006B1CEF /* CalendarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarViewController.swift; sourceTree = ""; }; - 8B6BD54F24293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepublishingNudgesViewControllerTests.swift; sourceTree = ""; }; 8B6EA62223FDE50B004BA312 /* PostServiceUploadingList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostServiceUploadingList.swift; sourceTree = ""; }; 8B749E7125AF522900023F03 /* JetpackCapabilitiesService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackCapabilitiesService.swift; sourceTree = ""; }; 8B749E8F25AF8D2E00023F03 /* JetpackCapabilitiesServiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackCapabilitiesServiceTests.swift; sourceTree = ""; }; @@ -12435,7 +12433,6 @@ children = ( 59ECF87A1CB7061D00E68F25 /* PostSharingControllerTests.swift */, F18B43771F849F580089B817 /* PostAttachmentTests.swift */, - 8B6BD54F24293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift */, 0CB424F32ADF3CBE0080B807 /* PostSearchViewModelTests.swift */, ); name = Posts; @@ -23747,7 +23744,6 @@ B556EFCB1DCA374200728F93 /* DictionaryHelpersTests.swift in Sources */, DC06DFF927BD52BE00969974 /* WeeklyRoundupBackgroundTaskTests.swift in Sources */, 24C69A8B2612421900312D9A /* UserSettingsTests.swift in Sources */, - 8B6BD55024293FBE00DB8F28 /* PrepublishingNudgesViewControllerTests.swift in Sources */, DC13DB7E293FD09F00E33561 /* StatsInsightsStoreTests.swift in Sources */, ACACE3AE28D729FA000992F9 /* NoResultsViewControllerTests.swift in Sources */, 4A2C73E42A943DEA00ACE79E /* TaggedManagedObjectIDTests.swift in Sources */, diff --git a/WordPress/WordPressTest/PrepublishingNudgesViewControllerTests.swift b/WordPress/WordPressTest/PrepublishingNudgesViewControllerTests.swift deleted file mode 100644 index dd08fd80ac39..000000000000 --- a/WordPress/WordPressTest/PrepublishingNudgesViewControllerTests.swift +++ /dev/null @@ -1,45 +0,0 @@ -import XCTest -import Nimble - -@testable import WordPress - -class PrepublishingNudgesViewControllerTests: CoreDataTestCase { - - override class func setUp() { - super.setUp() - - let windowManager = WindowManager(window: UIWindow()) - - /// We need that in order to initialize the Authenticator, otherwise this test crashes - /// This is because we're using the NUXButton. Ideally, that component should be extracted - WordPressAuthenticationManager( - windowManager: windowManager, - remoteFeaturesStore: RemoteFeatureFlagStore() - ).initializeWordPressAuthenticator() - } - - /// Call the completion block when the "Publish" button is pressed - /// - func testCallCompletionBlockWhenButtonTapped() { - var post = PostBuilder(mainContext).build() - var returnedPost: AbstractPost? - let prepublishingViewController = PrepublishingViewController(post: post, identifiers: [.schedule, .visibility, .tags, .categories]) { result in - switch result { - case .completed(let completedPost): - if let completedPost = completedPost as? Post { - post = completedPost - } - case .dismissed: - () - } - returnedPost = post - } - _ = UINavigationController(rootViewController: prepublishingViewController) - prepublishingViewController.viewDidLoad() - - prepublishingViewController.publishButton.sendActions(for: .touchUpInside) - - expect(returnedPost).toEventually(equal(post)) - } - -} From bcfadf6b7f8e1271c5f18729a35898d1d90ab460 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 13:03:42 -0500 Subject: [PATCH 03/14] Improve SchedulingDatePickerViewController --- ...blishingViewController+JetpackSocial.swift | 5 +- .../PrepublishingViewController.swift | 24 +- .../Post/Scheduling/ChosenValueRow.swift | 61 ----- .../PublishSettingsViewController.swift | 17 +- .../SchedulingDatePickerViewController.swift | 210 ++++-------------- .../SchedulingViewControllerPresenter.swift | 53 ----- WordPress/WordPress.xcodeproj/project.pbxproj | 12 - 7 files changed, 65 insertions(+), 317 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Post/Scheduling/ChosenValueRow.swift delete mode 100644 WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingViewControllerPresenter.swift diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift index 905fe741827e..5119b9426956 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift @@ -143,12 +143,13 @@ private extension PrepublishingViewController { func makeNoConnectionViewModel() -> JetpackSocialNoConnectionViewModel { let context = post.managedObjectContext ?? coreDataStack.mainContext + let insets = EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0) guard let services = try? PublicizeService.allSupportedServices(in: context) else { - return .init(padding: EdgeInsets(.zero)) + return .init(padding: insets) } return .init(services: services, - padding: EdgeInsets(.zero), + padding: insets, preferredBackgroundColor: tableView.backgroundColor, onConnectTap: noConnectionConnectTapped(), onNotNowTap: noConnectionDismissTapped()) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 55d57df3dab0..482ff250da0b 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -401,22 +401,14 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource func didTapSchedule(_ indexPath: IndexPath) { transitionIfVoiceOverDisabled(to: .hidden) - let viewController = PresentableSchedulingViewControllerProvider.viewController( - sourceView: tableView.cellForRow(at: indexPath)?.contentView, - sourceRect: nil, - viewModel: publishSettingsViewModel, - updated: { [weak self] date in - WPAnalytics.track(.editorPostScheduledChanged, properties: Constants.analyticsDefaultProperty) - self?.publishSettingsViewModel.setDate(date) - self?.reloadData() - self?.updatePublishButtonLabel() - }, - onDismiss: { [weak self] in - self?.reloadData() - self?.transitionIfVoiceOverDisabled(to: .collapsed) - } - ) - present(viewController, animated: true) + + let viewController = SchedulingDatePickerViewController.make(viewModel: publishSettingsViewModel) { [weak self] date in + WPAnalytics.track(.editorPostScheduledChanged, properties: Constants.analyticsDefaultProperty) + self?.publishSettingsViewModel.setDate(date) + self?.reloadData() + self?.updatePublishButtonLabel() + } + navigationController?.pushViewController(viewController, animated: true) } // MARK: - Publish Button diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/ChosenValueRow.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/ChosenValueRow.swift deleted file mode 100644 index d052bdc6c050..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/ChosenValueRow.swift +++ /dev/null @@ -1,61 +0,0 @@ -import Foundation - -/// A view with a title and detail label similar to the detail table view cell -class ChosenValueRow: UIView { - - private struct Constants { - static let rowHeight: CGFloat = 44 - static let rowInsets = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) - } - - let titleLabel: UILabel = { - let label = UILabel() - label.accessibilityTraits = .header - return label - }() - - let detailLabel = UILabel() - - override init(frame: CGRect) { - super.init(frame: frame) - - setupViews() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func setupViews() { - titleLabel.font = UIFont.preferredFont(forTextStyle: .callout) - - if effectiveUserInterfaceLayoutDirection == .leftToRight { - // swiftlint:disable:next inverse_text_alignment - detailLabel.textAlignment = .right - } else { - // swiftlint:disable:next natural_text_alignment - detailLabel.textAlignment = .left - } - detailLabel.textColor = .textSubtle - - let stackView = UIStackView(arrangedSubviews: [ - titleLabel, - detailLabel - ]) - stackView.distribution = .fillProportionally - stackView.translatesAutoresizingMaskIntoConstraints = false - - addSubview(stackView) - setupConstraints(stackView: stackView) - } - - private func setupConstraints(stackView: UIView) { - pinSubviewToAllEdges(stackView, insets: Constants.rowInsets) - - let heightConstraint = stackView.heightAnchor.constraint(equalToConstant: Constants.rowHeight) - heightConstraint.priority = .defaultHigh - NSLayoutConstraint.activate([ - heightConstraint - ]) - } -} diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift index 5f381f171f3c..0661d95394a0 100644 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift @@ -170,7 +170,7 @@ private struct DateAndTimeRow: ImmuTableRow { title: NSLocalizedString("Date and Time", comment: "Date and Time"), detail: viewModel.detailString, accessibilityIdentifier: "Date and Time Row", - action: presenter.present(dateTimeCalendarViewController(with: viewModel)) + action: presenter.push(dateTimeCalendarViewController(with: viewModel)) ) } } @@ -201,16 +201,11 @@ private struct DateAndTimeRow: ImmuTableRow { func dateTimeCalendarViewController(with model: PublishSettingsViewModel) -> (ImmuTableRow) -> UIViewController { return { [weak self] _ in - return PresentableSchedulingViewControllerProvider.viewController( - sourceView: self?.viewController?.tableView, - sourceRect: self?.rectForSelectedRow() ?? .zero, - viewModel: model, - updated: { [weak self] date in - WPAnalytics.track(.editorPostScheduledChanged, properties: ["via": "settings"]) - self?.viewModel.setDate(date) - NotificationCenter.default.post(name: Foundation.Notification.Name(rawValue: ImmuTableViewController.modelChangedNotification), object: nil) - }, - onDismiss: nil) + return SchedulingDatePickerViewController.make(viewModel: model) { [weak self] date in + WPAnalytics.track(.editorPostScheduledChanged, properties: ["via": "settings"]) + self?.viewModel.setDate(date) + NotificationCenter.default.post(name: Foundation.Notification.Name(rawValue: ImmuTableViewController.modelChangedNotification), object: nil) + } } } diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingDatePickerViewController.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingDatePickerViewController.swift index 86e9b5ff0c55..bf9f581d037b 100644 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingDatePickerViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingDatePickerViewController.swift @@ -2,201 +2,87 @@ import Foundation import Gridicons import UIKit -protocol DateCoordinatorHandler: AnyObject { - var coordinator: DateCoordinator? { get set } -} - -class DateCoordinator { - +struct SchedulingDatePickerConfiguration { var date: Date? - let timeZone: TimeZone - let dateFormatter: DateFormatter - let dateTimeFormatter: DateFormatter - let updated: (Date?) -> Void - - init(date: Date?, timeZone: TimeZone, dateFormatter: DateFormatter, dateTimeFormatter: DateFormatter, updated: @escaping (Date?) -> Void) { - self.date = date - self.timeZone = timeZone - self.dateFormatter = dateFormatter - self.dateTimeFormatter = dateTimeFormatter - self.updated = updated - } + var timeZone: TimeZone + var dateFormatter: DateFormatter + var dateTimeFormatter: DateFormatter + var updated: (Date?) -> Void } -// MARK: - Date Picker - -class SchedulingDatePickerViewController: UIViewController, DatePickerSheet, DateCoordinatorHandler { - - var coordinator: DateCoordinator? = nil +final class SchedulingDatePickerViewController: UIViewController { + var configuration: SchedulingDatePickerConfiguration? - let chosenValueRow = ChosenValueRow(frame: .zero) - - lazy var datePickerView: UIDatePicker = { + private lazy var datePickerView: UIDatePicker = { let datePicker = UIDatePicker() datePicker.preferredDatePickerStyle = .inline datePicker.calendar = Calendar.current - if let timeZone = coordinator?.timeZone { + if let timeZone = configuration?.timeZone { datePicker.timeZone = timeZone } - datePicker.date = coordinator?.date ?? Date() + datePicker.date = configuration?.date ?? Date() datePicker.translatesAutoresizingMaskIntoConstraints = false datePicker.addTarget(self, action: #selector(datePickerValueChanged(sender:)), for: .valueChanged) - + datePicker.tintColor = UIColor.primary return datePicker }() - @objc private func datePickerValueChanged(sender: UIDatePicker) { - let date = sender.date - coordinator?.date = date - chosenValueRow.detailLabel.text = coordinator?.dateFormatter.string(from: date) - } - - private lazy var closeButton: UIBarButtonItem = { - let item = UIBarButtonItem(image: .gridicon(.cross), - style: .plain, - target: self, - action: #selector(closeButtonPressed)) - item.accessibilityLabel = NSLocalizedString("Close", comment: "Accessibility label for the date picker's close button.") - return item - }() - - private lazy var publishButton = UIBarButtonItem(title: NSLocalizedString("Publish immediately", comment: "Immediately publish button title"), style: .plain, target: self, action: #selector(SchedulingDatePickerViewController.publishImmediately)) - override func viewDidLoad() { super.viewDidLoad() - chosenValueRow.titleLabel.text = NSLocalizedString("Choose a date", comment: "Label for Publish date picker") - - let doneButton = UIBarButtonItem(title: NSLocalizedString("Done", comment: "Label for Done button"), style: .done, target: self, action: #selector(done)) - - navigationItem.setRightBarButton(doneButton, animated: false) - - setup(topView: chosenValueRow, pickerView: datePickerView) - view.tintColor = .editorPrimary - - setupForAccessibility() - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - preferredContentSize = calculatePreferredSize() - } - - private func calculatePreferredSize() -> CGSize { - let targetSize = CGSize(width: view.bounds.width, - height: UIView.layoutFittingCompressedSize.height) - return view.systemLayoutSizeFitting(targetSize) - } - - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - (segue.destination as? DateCoordinatorHandler)?.coordinator = coordinator - } + title = Strings.title - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - resetNavigationButtons() - } + datePickerView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(datePickerView) + NSLayoutConstraint.activate([ + datePickerView.topAnchor.constraint(equalTo: view.topAnchor), + datePickerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + datePickerView.trailingAnchor.constraint(equalTo: view.trailingAnchor) + ]) + view.backgroundColor = .systemBackground - @objc func closeButtonPressed() { - dismiss(animated: true, completion: nil) + updateNavigationItems() } - override func accessibilityPerformEscape() -> Bool { - dismiss(animated: true, completion: nil) - return true + @objc private func buttonNowTapped() { + setDate(nil) + navigationController?.popViewController(animated: true) } - @objc func publishImmediately() { - coordinator?.updated(nil) - navigationController?.dismiss(animated: true, completion: nil) + @objc private func datePickerValueChanged(sender: UIDatePicker) { + setDate(sender.date) } - @objc func done() { - coordinator?.updated(coordinator?.date) - navigationController?.dismiss(animated: true, completion: nil) + private func setDate(_ date: Date?) { + configuration?.date = date + configuration?.updated(date) + updateNavigationItems() } - @objc private func resetNavigationButtons() { - let includeCloseButton = traitCollection.verticalSizeClass == .compact || - (isVoiceOverOrSwitchControlRunning && navigationController?.modalPresentationStyle != .popover) - - if includeCloseButton { - navigationItem.leftBarButtonItems = [closeButton, publishButton] + private func updateNavigationItems() { + if configuration?.date != nil { + navigationItem.rightBarButtonItem = UIBarButtonItem(title: Strings.now, style: .plain, target: self, action: #selector(buttonNowTapped)) } else { - navigationItem.leftBarButtonItems = [publishButton] + navigationItem.rightBarButtonItem = nil } } } -// MARK: Accessibility - -private extension SchedulingDatePickerViewController { - func setupForAccessibility() { - let notificationNames = [ - UIAccessibility.voiceOverStatusDidChangeNotification, - UIAccessibility.switchControlStatusDidChangeNotification - ] - NotificationCenter.default.addObserver(self, - selector: #selector(resetNavigationButtons), - names: notificationNames, - object: nil) - } - - var isVoiceOverOrSwitchControlRunning: Bool { - UIAccessibility.isVoiceOverRunning || UIAccessibility.isSwitchControlRunning - } -} - -// MARK: DatePickerSheet Protocol -protocol DatePickerSheet { - func configureStackView(topView: UIView, pickerView: UIView) -> UIView -} - -extension DatePickerSheet { - /// Constructs a view with `topView` on top and `pickerView` on bottom - /// - Parameter topView: A view to be shown above `pickerView` - /// - Parameter pickerView: A view to be shown on the bottom - func configureStackView(topView: UIView, pickerView: UIView) -> UIView { - pickerView.translatesAutoresizingMaskIntoConstraints = false - - let pickerWrapperView = UIView() - pickerWrapperView.addSubview(pickerView) - - let sideConstraints: [NSLayoutConstraint] = [ - pickerView.leftAnchor.constraint(equalTo: pickerWrapperView.leftAnchor), - pickerView.rightAnchor.constraint(equalTo: pickerWrapperView.rightAnchor) - ] - - NSLayoutConstraint.activate([ - pickerView.centerXAnchor.constraint(equalTo: pickerWrapperView.safeCenterXAnchor), - pickerView.topAnchor.constraint(equalTo: pickerWrapperView.topAnchor), - pickerView.bottomAnchor.constraint(equalTo: pickerWrapperView.bottomAnchor) - ]) - - NSLayoutConstraint.activate(sideConstraints) - - let stackView = UIStackView(arrangedSubviews: [ - topView, - pickerWrapperView - ]) - stackView.axis = .vertical - stackView.translatesAutoresizingMaskIntoConstraints = false - - return stackView +extension SchedulingDatePickerViewController { + static func make(viewModel: PublishSettingsViewModel, onDateUpdated: @escaping (Date?) -> Void) -> SchedulingDatePickerViewController { + let viewController = SchedulingDatePickerViewController() + viewController.configuration = SchedulingDatePickerConfiguration( + date: viewModel.date, + timeZone: viewModel.timeZone, + dateFormatter: viewModel.dateFormatter, + dateTimeFormatter: viewModel.dateTimeFormatter, + updated: onDateUpdated + ) + return viewController } } -extension DatePickerSheet where Self: UIViewController { - /// Adds `topView` and `pickerView` to view hierarchy + standard styling for the view controller's view - /// - Parameter topView: A view to show above `pickerView` (see `ChosenValueRow`) - /// - Parameter pickerView: A view to show below the top view - func setup(topView: UIView, pickerView: UIView) { - WPStyleGuide.configureColors(view: view, tableView: nil) - - let stackView = configureStackView(topView: topView, pickerView: pickerView) - - view.addSubview(stackView) - - view.pinSubviewToSafeArea(stackView) - } +private enum Strings { + static let title = NSLocalizedString("publishDatePicker.title", value: "Publish Date", comment: "Post publish date picker") + static let now = NSLocalizedString("publishDatePicker.now", value: "Now", comment: "The Now button that clears the date selection") } diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingViewControllerPresenter.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingViewControllerPresenter.swift deleted file mode 100644 index 4cc36b9ce7ca..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/SchedulingViewControllerPresenter.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Foundation -import UIKit - -class PresentableSchedulingViewControllerProvider { - static func viewController(sourceView: UIView?, - sourceRect: CGRect?, - viewModel: PublishSettingsViewModel, - updated: @escaping (Date?) -> Void, - onDismiss: (() -> Void)?) -> UINavigationController { - let schedulingViewController = schedulingViewController(with: viewModel, updated: updated) - return wrappedSchedulingViewController(schedulingViewController, - sourceView: sourceView, - sourceRect: sourceRect, - onDismiss: onDismiss) - } - - static func wrappedSchedulingViewController(_ schedulingViewController: SchedulingDatePickerViewController, - sourceView: UIView?, - sourceRect: CGRect?, - onDismiss: (() -> Void)?) -> SchedulingLightNavigationController { - let vc = SchedulingLightNavigationController(rootViewController: schedulingViewController) - vc.onDismiss = onDismiss - - if UIDevice.isPad() { - vc.modalPresentationStyle = .popover - if let popoverController = vc.popoverPresentationController, - let sourceView = sourceView { - popoverController.sourceView = sourceView - popoverController.sourceRect = sourceRect ?? sourceView.frame - } - } - return vc - } - - static func schedulingViewController(with viewModel: PublishSettingsViewModel, updated: @escaping (Date?) -> Void) -> SchedulingDatePickerViewController { - let schedulingViewController = SchedulingDatePickerViewController() - schedulingViewController.coordinator = DateCoordinator(date: viewModel.date, - timeZone: viewModel.timeZone, - dateFormatter: viewModel.dateFormatter, - dateTimeFormatter: viewModel.dateTimeFormatter, - updated: updated) - return schedulingViewController - } -} - -class SchedulingLightNavigationController: LightNavigationController { - var onDismiss: (() -> Void)? - - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - onDismiss?() - } -} diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 55ef409e4a20..75ee0441554a 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -250,8 +250,6 @@ 02D75D9922793EA2003FF09A /* BlogDetailsSectionFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02D75D9822793EA2003FF09A /* BlogDetailsSectionFooterView.swift */; }; 03216EC6279946CA00D444CA /* SchedulingDatePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03216EC5279946CA00D444CA /* SchedulingDatePickerViewController.swift */; }; 03216EC7279946CA00D444CA /* SchedulingDatePickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03216EC5279946CA00D444CA /* SchedulingDatePickerViewController.swift */; }; - 03216ECC27995F3500D444CA /* SchedulingViewControllerPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03216ECB27995F3500D444CA /* SchedulingViewControllerPresenter.swift */; }; - 03216ECD27995F3500D444CA /* SchedulingViewControllerPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03216ECB27995F3500D444CA /* SchedulingViewControllerPresenter.swift */; }; 069A4AA62664448F00413FA9 /* GutenbergFeaturedImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 069A4AA52664448F00413FA9 /* GutenbergFeaturedImageHelper.swift */; }; 069A4AA72664448F00413FA9 /* GutenbergFeaturedImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 069A4AA52664448F00413FA9 /* GutenbergFeaturedImageHelper.swift */; }; 080C44A91CE14A9F00B3A02F /* MenuDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 080C449E1CE14A9F00B3A02F /* MenuDetailsViewController.m */; }; @@ -3856,7 +3854,6 @@ F574416E242569CA00E150A8 /* Route+Page.swift in Sources */ = {isa = PBXBuildFile; fileRef = F574416C2425697D00E150A8 /* Route+Page.swift */; }; F580C3C123D22E2D0038E243 /* PreviewDeviceLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F580C3C023D22E2D0038E243 /* PreviewDeviceLabel.swift */; }; F582060223A85495005159A9 /* SiteDateFormatters.swift in Sources */ = {isa = PBXBuildFile; fileRef = F582060123A85495005159A9 /* SiteDateFormatters.swift */; }; - F59AAC10235E430F00385EE6 /* ChosenValueRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59AAC0F235E430E00385EE6 /* ChosenValueRow.swift */; }; F59AAC16235EA46D00385EE6 /* LightNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59AAC15235EA46D00385EE6 /* LightNavigationController.swift */; }; F5A34A9925DEF47D00C9654B /* WPMediaPicker+MediaPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5A34A9825DEF47D00C9654B /* WPMediaPicker+MediaPicker.swift */; }; F5A34BCB25DF244F00C9654B /* KanvasCameraAnalyticsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5A34BC925DF244F00C9654B /* KanvasCameraAnalyticsHandler.swift */; }; @@ -5159,7 +5156,6 @@ FABB25062602FC2C00C8785C /* ReaderTagsTableViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5A738C2244E7A6F00EDE065 /* ReaderTagsTableViewModel.swift */; }; FABB25072602FC2C00C8785C /* SiteAssemblyService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73178C2E21BEE1F500E37C9A /* SiteAssemblyService.swift */; }; FABB25082602FC2C00C8785C /* ManagedPerson.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5176CC01CDCE1B90083CF2D /* ManagedPerson.swift */; }; - FABB25092602FC2C00C8785C /* ChosenValueRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = F59AAC0F235E430E00385EE6 /* ChosenValueRow.swift */; }; FABB250A2602FC2C00C8785C /* ReplyTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B54E1DEE1A0A7BAA00807537 /* ReplyTextView.swift */; }; FABB250C2602FC2C00C8785C /* MenuItemEditingFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 08216FB11CDBF96000304BA7 /* MenuItemEditingFooterView.m */; }; FABB250D2602FC2C00C8785C /* ReaderCrossPostCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6D3E8481BEBD871002692E8 /* ReaderCrossPostCell.swift */; }; @@ -5951,7 +5947,6 @@ 02BF978AFC1EFE50CFD558C2 /* Pods-JetpackStatsWidgets.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JetpackStatsWidgets.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JetpackStatsWidgets/Pods-JetpackStatsWidgets.release.xcconfig"; sourceTree = ""; }; 02D75D9822793EA2003FF09A /* BlogDetailsSectionFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDetailsSectionFooterView.swift; sourceTree = ""; }; 03216EC5279946CA00D444CA /* SchedulingDatePickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchedulingDatePickerViewController.swift; sourceTree = ""; }; - 03216ECB27995F3500D444CA /* SchedulingViewControllerPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchedulingViewControllerPresenter.swift; sourceTree = ""; }; 069A4AA52664448F00413FA9 /* GutenbergFeaturedImageHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GutenbergFeaturedImageHelper.swift; sourceTree = ""; }; 080C449D1CE14A9F00B3A02F /* MenuDetailsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuDetailsViewController.h; sourceTree = ""; }; 080C449E1CE14A9F00B3A02F /* MenuDetailsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenuDetailsViewController.m; sourceTree = ""; }; @@ -9182,7 +9177,6 @@ F574416C2425697D00E150A8 /* Route+Page.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Route+Page.swift"; sourceTree = ""; }; F580C3C023D22E2D0038E243 /* PreviewDeviceLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewDeviceLabel.swift; sourceTree = ""; }; F582060123A85495005159A9 /* SiteDateFormatters.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDateFormatters.swift; sourceTree = ""; }; - F59AAC0F235E430E00385EE6 /* ChosenValueRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChosenValueRow.swift; sourceTree = ""; }; F59AAC15235EA46D00385EE6 /* LightNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightNavigationController.swift; sourceTree = ""; }; F5A34A9825DEF47D00C9654B /* WPMediaPicker+MediaPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "WPMediaPicker+MediaPicker.swift"; sourceTree = ""; }; F5A34BC925DF244F00C9654B /* KanvasCameraAnalyticsHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KanvasCameraAnalyticsHandler.swift; sourceTree = ""; }; @@ -17937,10 +17931,8 @@ children = ( F511F8A32356A4F400895E73 /* PublishSettingsViewController.swift */, F5660D06235D114500020B1E /* CalendarCollectionView.swift */, - F59AAC0F235E430E00385EE6 /* ChosenValueRow.swift */, F5660D08235D1CDD00020B1E /* CalendarMonthView.swift */, 03216EC5279946CA00D444CA /* SchedulingDatePickerViewController.swift */, - 03216ECB27995F3500D444CA /* SchedulingViewControllerPresenter.swift */, F59AAC15235EA46D00385EE6 /* LightNavigationController.swift */, F57402A6235FF9C300374346 /* SchedulingDate+Helpers.swift */, ); @@ -22367,7 +22359,6 @@ 31EC15081A5B6675009FC8B3 /* WPStyleGuide+Suggestions.m in Sources */, 9865257D2194D77F0078B916 /* SiteStatsInsightsViewModel.swift in Sources */, 9F74696B209EFD0C0074D52B /* CheckmarkTableViewCell.swift in Sources */, - 03216ECC27995F3500D444CA /* SchedulingViewControllerPresenter.swift in Sources */, F52CACCA244FA7AA00661380 /* ReaderManageScenePresenter.swift in Sources */, 0840513E2A4DDE3400A596E6 /* CompliancePopoverCoordinator.swift in Sources */, FF5371631FDFF64F00619A3F /* MediaService.swift in Sources */, @@ -22602,7 +22593,6 @@ 837B49DB283C2AE80061A657 /* BloggingPromptSettingsReminderDays+CoreDataClass.swift in Sources */, 73C8F06421BEEF3400DDDF7E /* SiteAssemblyService.swift in Sources */, B5176CC11CDCE1B90083CF2D /* ManagedPerson.swift in Sources */, - F59AAC10235E430F00385EE6 /* ChosenValueRow.swift in Sources */, FA98B61C29A3DB840071AAE8 /* BlazeHelper.swift in Sources */, B54E1DF11A0A7BAA00807537 /* ReplyTextView.swift in Sources */, 931215EE267F6799008C3B69 /* ReferrerDetailsCell.swift in Sources */, @@ -25059,7 +25049,6 @@ FABB23F12602FC2C00C8785C /* DefaultStockPhotosService.swift in Sources */, FABB23F22602FC2C00C8785C /* Animator.swift in Sources */, F4FF50E82B4D7D590076DB0C /* SubmitFeedbackViewController.swift in Sources */, - 03216ECD27995F3500D444CA /* SchedulingViewControllerPresenter.swift in Sources */, FABB23F32602FC2C00C8785C /* SiteStatsDashboardViewController.swift in Sources */, F4141EEC2AE945C7000D2AAE /* AllDomainsListItemViewModel.swift in Sources */, 9895401226C1F39300EDEB5A /* EditCommentTableViewController.swift in Sources */, @@ -25463,7 +25452,6 @@ 3F8B45A7292C1A2300730FA4 /* MigrationSuccessCardView.swift in Sources */, FABB25072602FC2C00C8785C /* SiteAssemblyService.swift in Sources */, FABB25082602FC2C00C8785C /* ManagedPerson.swift in Sources */, - FABB25092602FC2C00C8785C /* ChosenValueRow.swift in Sources */, FABB250A2602FC2C00C8785C /* ReplyTextView.swift in Sources */, FABB250C2602FC2C00C8785C /* MenuItemEditingFooterView.m in Sources */, FABB250D2602FC2C00C8785C /* ReaderCrossPostCell.swift in Sources */, From 1e41761990e97a5ca39f66edc000f3b2c2a8b88c Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 14:59:49 -0500 Subject: [PATCH 04/14] Present PostSettingsViewController in both the editor and the list --- .../Post/PostEditor+MoreOptions.swift | 8 ++++++-- .../PublishSettingsViewController.swift | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift index b797b9bf30c8..add7d24a1869 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift @@ -11,8 +11,12 @@ extension PostEditor { settingsViewController = PostSettingsViewController(post: post) } settingsViewController.featuredImageDelegate = self as? FeaturedImageDelegate - settingsViewController.hidesBottomBarWhenPushed = true - self.navigationController?.pushViewController(settingsViewController, animated: true) + settingsViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: .init(handler: { [weak self] _ in + self?.navigationController?.dismiss(animated: true) + })) + + let navigation = UINavigationController(rootViewController: settingsViewController) + self.navigationController?.present(navigation, animated: true) } private func createPostRevisionBeforePreview(completion: @escaping (() -> Void)) { diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift index 0661d95394a0..7db922f1c83d 100644 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Scheduling/PublishSettingsViewController.swift @@ -170,7 +170,7 @@ private struct DateAndTimeRow: ImmuTableRow { title: NSLocalizedString("Date and Time", comment: "Date and Time"), detail: viewModel.detailString, accessibilityIdentifier: "Date and Time Row", - action: presenter.push(dateTimeCalendarViewController(with: viewModel)) + action: UIDevice.isPad() ? presenter.present(dateTimeCalendarViewController(with: viewModel)) : presenter.push(dateTimeCalendarViewController(with: viewModel)) ) } } @@ -201,11 +201,23 @@ private struct DateAndTimeRow: ImmuTableRow { func dateTimeCalendarViewController(with model: PublishSettingsViewModel) -> (ImmuTableRow) -> UIViewController { return { [weak self] _ in - return SchedulingDatePickerViewController.make(viewModel: model) { [weak self] date in + let viewController = SchedulingDatePickerViewController.make(viewModel: model) { [weak self] date in WPAnalytics.track(.editorPostScheduledChanged, properties: ["via": "settings"]) self?.viewModel.setDate(date) NotificationCenter.default.post(name: Foundation.Notification.Name(rawValue: ImmuTableViewController.modelChangedNotification), object: nil) } + + if UIDevice.isPad() { + let navigation = UINavigationController(rootViewController: viewController) + navigation.modalPresentationStyle = .popover + if let popoverController = navigation.popoverPresentationController { + popoverController.sourceView = self?.viewController?.tableView + popoverController.sourceRect = self?.rectForSelectedRow() ?? .zero + } + return navigation + } + + return viewController } } From ea3570f8edd4a753c143f5aa93a509408b262b74 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 16:34:59 -0500 Subject: [PATCH 05/14] Refactor PrepublishingViewController --- .../PostCategoriesViewController.swift | 4 -- .../ViewRelated/Post/PostEditor+Publish.swift | 30 +++++------ .../Post/PostTagPickerViewController.swift | 11 ---- .../PrepublishingHeaderView.swift | 4 +- ...blishingSocialAccountsViewController.swift | 13 ----- ...blishingViewController+JetpackSocial.swift | 12 +---- .../PrepublishingViewController.swift | 54 +++---------------- 7 files changed, 25 insertions(+), 103 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/Categories/PostCategoriesViewController.swift b/WordPress/Classes/ViewRelated/Post/Categories/PostCategoriesViewController.swift index 947d6edf4bad..5a6f8002f240 100644 --- a/WordPress/Classes/ViewRelated/Post/Categories/PostCategoriesViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Categories/PostCategoriesViewController.swift @@ -15,7 +15,6 @@ import Foundation @objc weak var delegate: PostCategoriesViewControllerDelegate? var onCategoriesChanged: (() -> Void)? - var onTableViewHeightDetermined: (() -> Void)? private var blog: Blog private var originalSelection: [PostCategory]? @@ -50,9 +49,6 @@ import Foundation if !hasSyncedCategories { syncCategories() } - - preferredContentSize = tableView.contentSize - onTableViewHeightDetermined?() } override func viewWillDisappear(_ animated: Bool) { diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift index 443618608da4..fbb9bf1746f1 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift @@ -251,23 +251,23 @@ extension PublishingEditor { let shouldDisplayPortrait = WPDeviceIdentification.isiPhone() && isTitleDisplayed let prepublishingNavigationController = PrepublishingNavigationController(rootViewController: prepublishing, shouldDisplayPortrait: shouldDisplayPortrait) - // TODO: make it work on iPad // TODO: make it work in other places - // TODO: compute size dynamically - if let sheetController = prepublishingNavigationController.sheetPresentationController { - if #available(iOS 16, *) { - sheetController.detents = [ - .custom(resolver: { context in - return 540 - }), - .large() - ] - sheetController.prefersGrabberVisible = true - sheetController.preferredCornerRadius = 16 - prepublishingNavigationController.additionalSafeAreaInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) + if UIDevice.isPad() { + prepublishingNavigationController.modalPresentationStyle = .formSheet + } else { + if let sheetController = prepublishingNavigationController.sheetPresentationController { + if #available(iOS 16, *) { + sheetController.detents = [ + .custom(resolver: { context in + return 520 + }), + .large() + ] + sheetController.prefersGrabberVisible = true + sheetController.preferredCornerRadius = 16 + prepublishingNavigationController.additionalSafeAreaInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) + } } - } else if let popoverController = prepublishingNavigationController.popoverPresentationController { - // TODO: complete on iPad (preferredContentSize) } topmostPresentedViewController.present(prepublishingNavigationController, animated: true) } diff --git a/WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift b/WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift index e113d80f4529..103eed3b95ac 100644 --- a/WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/PostTagPickerViewController.swift @@ -34,8 +34,6 @@ class PostTagPickerViewController: UIViewController { } } - var onContentViewHeightDetermined: (() -> Void)? - override func viewDidLoad() { super.viewDidLoad() @@ -118,7 +116,6 @@ class PostTagPickerViewController: UIViewController { super.viewWillAppear(animated) textView.becomeFirstResponder() - updateContainerHeight() } override func viewDidAppear(_ animated: Bool) { @@ -164,14 +161,6 @@ class PostTagPickerViewController: UIViewController { tableView.contentInset.bottom += presentedVC?.yPosition ?? 0 } - - fileprivate func updateContainerHeight() { - descriptionLabel.layoutIfNeeded() - textViewContainer.layoutIfNeeded() - let contentHeight = tableView.contentSize.height + descriptionLabel.bounds.size.height + textViewContainer.bounds.height - preferredContentSize = CGSize(width: view.bounds.width, height: max(300.0, contentHeight)) - onContentViewHeightDetermined?() - } } // MARK: - Tags Loading diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift index 28b6dd20f8c1..ccec7d762d89 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift @@ -78,6 +78,6 @@ final class PrepublishingHeaderView: UIView { } private enum Strings { - static let close = NSLocalizedString("prepublishingSheet.pubishingTo", value: "Close", comment: "Voiceover accessibility label informing the user that this button dismiss the current view") - static let publishingTo = NSLocalizedString("prepublishingSheet.pubishingTo", value: "Publishing to", comment: "Label in the header in the pre-publishing sheet") + static let close = NSLocalizedString("prepublishing.pubishingTo", value: "Close", comment: "Voiceover accessibility label informing the user that this button dismiss the current view") + static let publishingTo = NSLocalizedString("prepublishing.pubishingTo", value: "Publishing to", comment: "Label in the header in the pre-publishing sheet") } diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingSocialAccountsViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingSocialAccountsViewController.swift index 7546d2221a1e..9ac08aee5eef 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingSocialAccountsViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingSocialAccountsViewController.swift @@ -39,8 +39,6 @@ class PrepublishingSocialAccountsViewController: UITableViewController { } } - var onContentHeightUpdated: (() -> Void)? = nil - /// Stores the interaction state for disabled connections. /// The value is stored in order to perform table operations *only* when the value changes. private var canInteractWithDisabledConnections: Bool { @@ -116,17 +114,6 @@ class PrepublishingSocialAccountsViewController: UITableViewController { tableView.tableHeaderView = UIView(frame: .init(x: 0, y: 0, width: 0, height: Constants.tableTopPadding)) } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - - // manually configure preferredContentSize for precise drawer sizing. - let bottomInset = max(UIApplication.shared.mainWindow?.safeAreaInsets.bottom ?? 0, Constants.defaultBottomInset) - let contentHeight = tableView.contentSize.height + bottomInset + Constants.additionalBottomInset - preferredContentSize = CGSize(width: tableView.contentSize.width, - height: max(contentHeight, Constants.minContentHeight)) - onContentHeightUpdated?() - } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift index 5119b9426956..97a0b64a4adf 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController+JetpackSocial.swift @@ -45,10 +45,6 @@ extension PrepublishingViewController { delegate: self, coreDataStack: coreDataStack) - socialAccountsViewController.onContentHeightUpdated = { [weak self] in - self?.presentedVC?.containerViewWillLayoutSubviews() - } - self.navigationController?.pushViewController(socialAccountsViewController, animated: true) } } @@ -191,13 +187,7 @@ private extension PrepublishingViewController { self.tableView.performBatchUpdates { self.tableView.deleteRows(at: [.init(row: autoSharingRowIndex, section: .zero)], with: .fade) - } completion: { _ in - self.presentedVC?.transition(to: .collapsed) - } - - // when displayed in a popover view (i.e. iPad), updating the content size will resize - // the popover window to fit the updated content. - self.navigationController?.preferredContentSize = self.tableView.contentSize + } completion: { _ in } } } diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 482ff250da0b..ed026d8de8cd 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -147,7 +147,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource view.pinSubviewToSafeArea(stackView) setupPublishButton() - setupFooterSeparator() updatePublishButtonLabel() announcePublishButton() @@ -183,8 +182,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - // TODO: remove/reimplemnet? - preferredContentSize = tableView.contentSize footerSeparator.isHidden = tableView.contentSize.height < tableView.bounds.height } @@ -339,29 +336,21 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource self?.reloadData() } - tagPickerViewController.onContentViewHeightDetermined = { [weak self] in - self?.presentedVC?.containerViewWillLayoutSubviews() - } - navigationController?.pushViewController(tagPickerViewController, animated: true) } private func configureCategoriesCell(_ cell: WPTableViewCell) { - cell.detailTextLabel?.text = Array(post.categories ?? []).map { $0.categoryName }.joined(separator: ",") + cell.detailTextLabel?.text = Array(post.categories ?? []) + .map { $0.categoryName } + .joined(separator: ",") } private func didTapCategoriesCell() { let categoriesViewController = PostCategoriesViewController(blog: post.blog, currentSelection: Array(post.categories ?? []), selectionMode: .post) categoriesViewController.delegate = self categoriesViewController.onCategoriesChanged = { [weak self] in - self?.presentedVC?.containerViewWillLayoutSubviews() self?.tableView.reloadData() } - - categoriesViewController.onTableViewHeightDetermined = { [weak self] in - self?.presentedVC?.containerViewWillLayoutSubviews() - } - navigationController?.pushViewController(categoriesViewController, animated: true) } @@ -394,14 +383,12 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource // MARK: - Schedule func configureScheduleCell(_ cell: WPTableViewCell) { - cell.textLabel?.text = post.shouldPublishImmediately() ? Constants.publishDateLabel : Constants.scheduledLabel + cell.textLabel?.text = Constants.publishDateLabel cell.detailTextLabel?.text = publishSettingsViewModel.detailString post.status == .publishPrivate ? cell.disable() : cell.enable() } func didTapSchedule(_ indexPath: IndexPath) { - transitionIfVoiceOverDisabled(to: .hidden) - let viewController = SchedulingDatePickerViewController.make(viewModel: publishSettingsViewModel) { [weak self] date in WPAnalytics.track(.editorPostScheduledChanged, properties: Constants.analyticsDefaultProperty) self?.publishSettingsViewModel.setDate(date) @@ -430,23 +417,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource updatePublishButtonLabel() } - private func setupFooterSeparator() { - guard let footer = tableView.tableFooterView else { - return - } - - let separator = UIView() - separator.translatesAutoresizingMaskIntoConstraints = false - footer.addSubview(separator) - NSLayoutConstraint.activate([ - separator.topAnchor.constraint(equalTo: footer.topAnchor), - separator.leftAnchor.constraint(equalTo: footer.leftAnchor), - separator.rightAnchor.constraint(equalTo: footer.rightAnchor), - separator.heightAnchor.constraint(equalToConstant: 1) - ]) - WPStyleGuide.applyBorderStyle(separator) - } - private func updatePublishButtonLabel() { publishButton.setTitle(post.isScheduled() ? Constants.scheduleNow : Constants.publishNow, for: .normal) } @@ -491,16 +461,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } } - /// Only perform a transition if Voice Over is disabled - /// This avoids some unresponsiveness - private func transitionIfVoiceOverDisabled(to position: DrawerPosition) { - guard !UIAccessibility.isVoiceOverRunning else { - return - } - - presentedVC?.transition(to: position) - } - + // TODO: cleanup fileprivate enum Constants { static let reuseIdentifier = "wpTableViewCell" static let textFieldReuseIdentifier = "wpTextFieldCell" @@ -508,7 +469,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource static let publishNow = NSLocalizedString("Publish Now", comment: "Label for a button that publishes the post") static let scheduleNow = NSLocalizedString("Schedule Now", comment: "Label for the button that schedules the post") static let publishDateLabel = NSLocalizedString("Publish Date", comment: "Label for Publish date") - static let scheduledLabel = NSLocalizedString("Scheduled for", comment: "Scheduled for [date]") static let titlePlaceholder = NSLocalizedString("Title", comment: "Placeholder for title") static let analyticsDefaultProperty = ["via": "prepublishing_nudges"] } @@ -516,8 +476,8 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource // TODO: Remove other ones private enum Strings { - static let publish = NSLocalizedString("prepublishingSheet.publish", value: "Publish", comment: "Label for a button that publishes the post") - static let schedule = NSLocalizedString("prepublishingSheet.schedule", value: "Schedule", comment: "Label for a button that publishes the post") + static let publish = NSLocalizedString("prepublishing.publish", value: "Publish", comment: "Label for a button that publishes the post") + static let schedule = NSLocalizedString("prepublishing.schedule", value: "Schedule", comment: "Label for a button that publishes the post") } // TODO: check this From 2390e65bc0f235b2125dcc78526509017b754f0e Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 17:57:09 -0500 Subject: [PATCH 06/14] Update localization in PrepublishingViewController --- .../ViewRelated/Post/PostEditor+Publish.swift | 4 +- .../PrepublishingViewController.swift | 51 ++++++++++--------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift index fbb9bf1746f1..2e8ba7fd6934 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift @@ -258,9 +258,7 @@ extension PublishingEditor { if let sheetController = prepublishingNavigationController.sheetPresentationController { if #available(iOS 16, *) { sheetController.detents = [ - .custom(resolver: { context in - return 520 - }), + .custom { _ in 520 }, .large() ] sheetController.prefersGrabberVisible = true diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index ed026d8de8cd..cce008805028 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -45,11 +45,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource return PublishSettingsViewModel(post: post) }() - #warning("TODO: remove") - var presentedVC: DrawerPresentationController? { - return (navigationController as? PrepublishingNavigationController)?.presentedVC - } - enum CompletionResult { case completed(AbstractPost) case dismissed @@ -210,6 +205,11 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource if isPresentingAViewController { navigationController?.setNavigationBarHidden(false, animated: animated) } + + if isBeingDismissed { + print("here") + // TODO: Do your stuff here. + } } // MARK: - UITableViewDataSource @@ -313,7 +313,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource cell.textField.adjustsFontForContentSizeCategory = true cell.textField.font = .preferredFont(forTextStyle: .body) cell.textField.textColor = .text - cell.textField.placeholder = Constants.titlePlaceholder + cell.textField.placeholder = Strings.postTitle cell.textField.heightAnchor.constraint(equalToConstant: 40).isActive = true cell.textField.autocorrectionType = .yes cell.textField.autocapitalizationType = .sentences @@ -383,7 +383,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource // MARK: - Schedule func configureScheduleCell(_ cell: WPTableViewCell) { - cell.textLabel?.text = Constants.publishDateLabel + cell.textLabel?.text = Strings.publishDate cell.detailTextLabel?.text = publishSettingsViewModel.detailString post.status == .publishPrivate ? cell.disable() : cell.enable() } @@ -418,7 +418,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } private func updatePublishButtonLabel() { - publishButton.setTitle(post.isScheduled() ? Constants.scheduleNow : Constants.publishNow, for: .normal) + publishButton.setTitle(post.isScheduled() ? Strings.schedule : Strings.publish, for: .normal) } @objc func publish(_ sender: UIButton) { @@ -461,25 +461,14 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } } - // TODO: cleanup fileprivate enum Constants { static let reuseIdentifier = "wpTableViewCell" static let textFieldReuseIdentifier = "wpTextFieldCell" static let nuxButtonInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) - static let publishNow = NSLocalizedString("Publish Now", comment: "Label for a button that publishes the post") - static let scheduleNow = NSLocalizedString("Schedule Now", comment: "Label for the button that schedules the post") - static let publishDateLabel = NSLocalizedString("Publish Date", comment: "Label for Publish date") - static let titlePlaceholder = NSLocalizedString("Title", comment: "Placeholder for title") static let analyticsDefaultProperty = ["via": "prepublishing_nudges"] } } -// TODO: Remove other ones -private enum Strings { - static let publish = NSLocalizedString("prepublishing.publish", value: "Publish", comment: "Label for a button that publishes the post") - static let schedule = NSLocalizedString("prepublishing.schedule", value: "Schedule", comment: "Label for a button that publishes the post") -} - // TODO: check this extension PrepublishingViewController: PrepublishingDismissible { func handleDismiss() { @@ -535,17 +524,29 @@ private extension PrepublishingOption { init(identifier: PrepublishingIdentifier) { switch identifier { case .title: - self.init(id: .title, title: PrepublishingViewController.Constants.titlePlaceholder, type: .textField) + self.init(id: .title, title: Strings.postTitle, type: .textField) case .schedule: - self.init(id: .schedule, title: PrepublishingViewController.Constants.publishDateLabel, type: .value) + self.init(id: .schedule, title: Strings.publishDate, type: .value) case .categories: - self.init(id: .categories, title: NSLocalizedString("Categories", comment: "Label for Categories"), type: .value) + self.init(id: .categories, title: Strings.categories, type: .value) case .visibility: - self.init(id: .visibility, title: NSLocalizedString("Visibility", comment: "Label for Visibility"), type: .value) + self.init(id: .visibility, title: Strings.visibility, type: .value) case .tags: - self.init(id: .tags, title: NSLocalizedString("Tags", comment: "Label for Tags"), type: .value) + self.init(id: .tags, title: Strings.tags, type: .value) case .autoSharing: - self.init(id: .autoSharing, title: "Jetpack Social", type: .customContainer) + self.init(id: .autoSharing, title: Strings.jetpackSocial, type: .customContainer) } } } + +// TODO: Remove other ones +private enum Strings { + static let publish = NSLocalizedString("prepublishing.publish", value: "Publish", comment: "Primary button label in the pre-publishing sheet") + static let schedule = NSLocalizedString("prepublishing.schedule", value: "Schedule", comment: "Primary button label in the pre-publishing shee") + static let publishDate = NSLocalizedString("prepublishing.publishDate", value: "Publish Date", comment: "Label for a cell in the pre-publishing sheet") + static let postTitle = NSLocalizedString("prepublishing.postTitle", value: "Title", comment: "Placeholder for a cell in the pre-publishing sheet") + static let visibility = NSLocalizedString("prepublishing.visibility", value: "Visibility", comment: "Label for a cell in the pre-publishing sheet") + static let categories = NSLocalizedString("prepublishing.categories", value: "Categories", comment: "Label for a cell in the pre-publishing sheet") + static let tags = NSLocalizedString("prepublishing.tags", value: "Tags", comment: "Label for a cell in the pre-publishing sheet") + static let jetpackSocial = NSLocalizedString("prepublishing.jetpackSocial", value: "Jetpack Social", comment: "Label for a cell in the pre-publishing sheet") +} From d2382238c06c7b2731019921bfffdb0bc5edb52d Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 18:02:58 -0500 Subject: [PATCH 07/14] Fix the dismiss logic in PrepublishingViewController.swift --- .../PrepublishingViewController.swift | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index cce008805028..913f0ecb988c 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -201,14 +201,18 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - let isPresentingAViewController = navigationController?.viewControllers.count ?? 0 > 1 - if isPresentingAViewController { + let isPushingViewController = navigationController?.viewControllers.count ?? 0 > 1 + if isPushingViewController { navigationController?.setNavigationBarHidden(false, animated: animated) } - if isBeingDismissed { - print("here") - // TODO: Do your stuff here. + if isBeingDismissed || parent?.isBeingDismissed == true { + if !didTapPublish, + post.status == .publishPrivate, + let originalStatus = post.original?.status { + post.status = originalStatus + } + completion(.dismissed) } } @@ -469,21 +473,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } } -// TODO: check this -extension PrepublishingViewController: PrepublishingDismissible { - func handleDismiss() { - defer { completion(.dismissed) } - guard - !didTapPublish, - post.status == .publishPrivate, - let originalStatus = post.original?.status else { - return - } - - post.status = originalStatus - } -} - extension PrepublishingViewController: WPTextFieldTableViewCellDelegate { func cellWants(toSelectNextField cell: WPTextFieldTableViewCell!) { From 9e8ea9c45a6c46f7a175246559be5749bb830b78 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 18:10:55 -0500 Subject: [PATCH 08/14] Remove unused code --- .../PrepublishingViewController.swift | 52 ++++++------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 913f0ecb988c..2fd98b09784b 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -19,8 +19,6 @@ enum PrepublishingIdentifier { } } -// TODO: Fix insets for "social" and "publish" -// TODO: Check if deinit works final class PrepublishingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { let post: Post let identifiers: [PrepublishingIdentifier] @@ -118,22 +116,15 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource configureHeader() configureTableView() configureKeyboardToggle() + WPStyleGuide.applyBorderStyle(footerSeparator) title = "" - // TODO: cleanup - let footer = UIView() - footer.addSubview(publishButton) - publishButton.translatesAutoresizingMaskIntoConstraints = false - footer.pinSubviewToAllEdges(publishButton, insets: Constants.nuxButtonInsets) - - WPStyleGuide.applyBorderStyle(footerSeparator) - let stackView = UIStackView(arrangedSubviews: [ headerView, tableView, footerSeparator, - footer + setupPublishButton() ]) stackView.axis = .vertical @@ -141,13 +132,9 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource stackView.translatesAutoresizingMaskIntoConstraints = false view.pinSubviewToSafeArea(stackView) - setupPublishButton() + view.backgroundColor = .systemBackground - updatePublishButtonLabel() announcePublishButton() - - // TODO: check dark mode - view.backgroundColor = .systemBackground } private func configureHeader() { @@ -163,6 +150,19 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource tableView.rowHeight = UITableView.automaticDimension } + private func setupPublishButton() -> UIView { + let footerView = UIView() + footerView.addSubview(publishButton) + publishButton.translatesAutoresizingMaskIntoConstraints = false + footerView.pinSubviewToSafeArea(publishButton, insets: Constants.nuxButtonInsets) + + publishButton.addTarget(self, action: #selector(publish), for: .touchUpInside) + + updatePublishButtonLabel() + + return footerView + } + /// Toggles `keyboardShown` as the keyboard notifications come in private func configureKeyboardToggle() { NotificationCenter.default.publisher(for: UIResponder.keyboardDidShowNotification) @@ -404,23 +404,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource // MARK: - Publish Button - // TODO: cleanuo - private func setupPublishButton() { - return () - - let footer = UIView() - footer.addSubview(publishButton) - publishButton.translatesAutoresizingMaskIntoConstraints = false - footer.pinSubviewToSafeArea(publishButton, insets: Constants.nuxButtonInsets) - - view.addSubview(footer) - footer.translatesAutoresizingMaskIntoConstraints = false - view.pinSubviewToSafeArea(footer, insets: .zero) - - publishButton.addTarget(self, action: #selector(publish), for: .touchUpInside) - updatePublishButtonLabel() - } - private func updatePublishButtonLabel() { publishButton.setTitle(post.isScheduled() ? Strings.schedule : Strings.publish, for: .normal) } @@ -468,7 +451,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource fileprivate enum Constants { static let reuseIdentifier = "wpTableViewCell" static let textFieldReuseIdentifier = "wpTextFieldCell" - static let nuxButtonInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + static let nuxButtonInsets = UIEdgeInsets(top: 16, left: 20, bottom: 16, right: 20) static let analyticsDefaultProperty = ["via": "prepublishing_nudges"] } } @@ -528,7 +511,6 @@ private extension PrepublishingOption { } } -// TODO: Remove other ones private enum Strings { static let publish = NSLocalizedString("prepublishing.publish", value: "Publish", comment: "Primary button label in the pre-publishing sheet") static let schedule = NSLocalizedString("prepublishing.schedule", value: "Schedule", comment: "Primary button label in the pre-publishing shee") From 2e901dc3ad632313669a33278c9e8f5a65b5f686 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 18:12:09 -0500 Subject: [PATCH 09/14] Remove unused PrepublishingNavigationController.swift --- .../Post/AbstractPostListViewController.swift | 6 +- .../ViewRelated/Post/PostEditor+Publish.swift | 25 +--- .../PrepublishingNavigationController.swift | 124 ------------------ .../PrepublishingViewController.swift | 30 ++++- WordPress/WordPress.xcodeproj/project.pbxproj | 6 - 5 files changed, 28 insertions(+), 163 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingNavigationController.swift diff --git a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift index f0c20314f473..80f263455686 100644 --- a/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/AbstractPostListViewController.swift @@ -601,7 +601,7 @@ class AbstractPostListViewController: UIViewController, let action = AbstractPostHelper.editorPublishAction(for: post) func showPrepublishingFlow(for post: Post) { - let prepublishing = PrepublishingViewController(post: post, identifiers: PrepublishingIdentifier.defaultIdentifiers) { [weak self] result in + let viewController = PrepublishingViewController(post: post, identifiers: PrepublishingIdentifier.defaultIdentifiers) { [weak self] result in switch result { case .completed(let post): self?.didConfirmPublish(for: post) @@ -609,9 +609,7 @@ class AbstractPostListViewController: UIViewController, break } } - let navigationController = PrepublishingNavigationController(rootViewController: prepublishing, shouldDisplayPortrait: false) - let bottomSheet = BottomSheetViewController(childViewController: navigationController, customHeaderSpacing: 0) - bottomSheet.show(from: self) + viewController.presentAsSheet(from: self) } func showPublishingConfirmation() { diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift index 2e8ba7fd6934..eb0b5742ac7b 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+Publish.swift @@ -237,7 +237,7 @@ extension PublishingEditor { // End editing to avoid issues with accessibility view.endEditing(true) - let prepublishing = PrepublishingViewController(post: post, identifiers: prepublishingIdentifiers) { [weak self] result in + let viewController = PrepublishingViewController(post: post, identifiers: prepublishingIdentifiers) { [weak self] result in switch result { case .completed(let post): self?.post = post @@ -246,28 +246,7 @@ extension PublishingEditor { dismissAction() } } - - let isTitleDisplayed = prepublishingIdentifiers.contains { $0 == .title } - let shouldDisplayPortrait = WPDeviceIdentification.isiPhone() && isTitleDisplayed - let prepublishingNavigationController = PrepublishingNavigationController(rootViewController: prepublishing, shouldDisplayPortrait: shouldDisplayPortrait) - - // TODO: make it work in other places - if UIDevice.isPad() { - prepublishingNavigationController.modalPresentationStyle = .formSheet - } else { - if let sheetController = prepublishingNavigationController.sheetPresentationController { - if #available(iOS 16, *) { - sheetController.detents = [ - .custom { _ in 520 }, - .large() - ] - sheetController.prefersGrabberVisible = true - sheetController.preferredCornerRadius = 16 - prepublishingNavigationController.additionalSafeAreaInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) - } - } - } - topmostPresentedViewController.present(prepublishingNavigationController, animated: true) + viewController.presentAsSheet(from: topmostPresentedViewController) } /// Displays a publish confirmation alert with two options: "Keep Editing" and String for Action. diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingNavigationController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingNavigationController.swift deleted file mode 100644 index 96652a25171d..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingNavigationController.swift +++ /dev/null @@ -1,124 +0,0 @@ -import UIKit -import WordPressUI - -protocol PrepublishingDismissible { - func handleDismiss() -} - -class PrepublishingNavigationController: LightNavigationController { - - private let shouldDisplayPortrait: Bool - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - shouldDisplayPortrait ? .portrait : .all - } - - // We are using intrinsicHeight as the view's collapsedHeight which is calculated from the preferredContentSize. - override public var preferredContentSize: CGSize { - set { - viewControllers.last?.preferredContentSize = newValue - super.preferredContentSize = newValue - } - get { - guard let visibleViewController = viewControllers.last else { - return .zero - } - - return visibleViewController.preferredContentSize - } - } - - override func pushViewController(_ viewController: UIViewController, animated: Bool) { - super.pushViewController(viewController, animated: animated) - - transition(for: viewController) - } - - override func popViewController(animated: Bool) -> UIViewController? { - let viewController = super.popViewController(animated: animated) - - transition(for: viewController) - - return viewController - } - - init(rootViewController: UIViewController, shouldDisplayPortrait: Bool) { - self.shouldDisplayPortrait = shouldDisplayPortrait - super.init(rootViewController: rootViewController) - - configureNavigationBar() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func transition(for viewController: UIViewController?) { - guard let bottomSheet = self.parent as? BottomSheetViewController, - let presentedVC = bottomSheet.presentedVC else { - return - } - - let preferredDrawerPosition: DrawerPosition = { - guard RemoteFeatureFlag.jetpackSocialImprovements.enabled() else { - return .collapsed - } - - if let positionable = viewController as? ChildDrawerPositionable { - return positionable.preferredDrawerPosition - } - - return traitCollection.preferredContentSizeCategory.isAccessibilityCategory ? .expanded : .collapsed - }() - - presentedVC.transition(to: preferredDrawerPosition) - } - - /// Updates the navigation bar color so it matches the view's background. - /// - /// Originally, in dark mode the navigation bar color is grayish, but there's a few points gap on top of the - /// navigation bar to accommodate the `GripButton` from `BottomSheetViewController`. The bottom sheet itself - /// assigns the background color according to its child controller's view background color. - private func configureNavigationBar() { - let appearance = UINavigationBarAppearance() - appearance.configureWithOpaqueBackground() - appearance.backgroundColor = .basicBackground - - navigationBar.scrollEdgeAppearance = appearance - navigationBar.compactAppearance = appearance - } -} - -// MARK: - DrawerPresentable - -extension PrepublishingNavigationController: DrawerPresentable { - var allowsUserTransition: Bool { - guard let visibleDrawer = visibleViewController as? DrawerPresentable else { - return true - } - - return visibleDrawer.allowsUserTransition - } - - var expandedHeight: DrawerHeight { - return .topMargin(20) - } - - var collapsedHeight: DrawerHeight { - guard let visibleDrawer = visibleViewController as? DrawerPresentable else { - return .contentHeight(300) - } - - return visibleDrawer.collapsedHeight - } - - var scrollableView: UIScrollView? { - return topViewController?.view as? UIScrollView - } - - func handleDismiss() { - if let rootViewController = viewControllers.first as? PrepublishingDismissible { - rootViewController.handleDismiss() - } - } -} diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 2fd98b09784b..3acedaf86e26 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -39,9 +39,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource options.map { $0.id } } - private lazy var publishSettingsViewModel: PublishSettingsViewModel = { - return PublishSettingsViewModel(post: post) - }() + private lazy var publishSettingsViewModel = PublishSettingsViewModel(post: post) enum CompletionResult { case completed(AbstractPost) @@ -59,7 +57,6 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource let tableView = UITableView(frame: .zero, style: .plain) private let footerSeparator = UIView() - // TODO: make private let publishButton: NUXButton = { let nuxButton = NUXButton() nuxButton.isPrimary = true @@ -72,6 +69,9 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource /// Determines whether the text has been first responder already. If it has, don't force it back on the user unless it's been selected by them. private var hasSelectedText: Bool = false + private var cancellables = Set() + @Published private var keyboardShown: Bool = false + init(post: Post, identifiers: [PrepublishingIdentifier], completion: @escaping (CompletionResult) -> (), @@ -89,8 +89,24 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource fatalError("init(coder:) has not been implemented") } - private var cancellables = Set() - @Published private var keyboardShown: Bool = false + func presentAsSheet(from presentingViewController: UIViewController) { + let navigationController = UINavigationController(rootViewController: self) + if UIDevice.isPad() { + navigationController.modalPresentationStyle = .formSheet + } else { + if let sheetController = navigationController.sheetPresentationController { + if #available(iOS 16, *) { + sheetController.detents = [.custom { _ in 520 }, .large()] + } else { + sheetController.detents = [.medium(), .large()] + } + sheetController.prefersGrabberVisible = true + sheetController.preferredCornerRadius = 16 + navigationController.additionalSafeAreaInsets = UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0) + } + } + presentingViewController.present(navigationController, animated: true) + } func refreshOptions() { options = identifiers.compactMap { identifier -> PrepublishingOption? in @@ -108,6 +124,8 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } } + // MARK: - View + override func viewDidLoad() { super.viewDidLoad() diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 75ee0441554a..ed121e0ad17d 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -2227,7 +2227,6 @@ 8B05D29323AA572A0063B9AA /* GutenbergMediaEditorImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B05D29223AA572A0063B9AA /* GutenbergMediaEditorImage.swift */; }; 8B0732E9242BA1F000E7FBD3 /* PrepublishingHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */; }; 8B0732F0242BF7E800E7FBD3 /* Blog+Title.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */; }; - 8B0732F3242BF99B00E7FBD3 /* PrepublishingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */; }; 8B074A5027AC3A64003A2EB8 /* BlogDashboardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B074A4F27AC3A64003A2EB8 /* BlogDashboardViewModel.swift */; }; 8B074A5127AC3A64003A2EB8 /* BlogDashboardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B074A4F27AC3A64003A2EB8 /* BlogDashboardViewModel.swift */; }; 8B0CE7D12481CFE8004C4799 /* ReaderDetailHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0CE7D02481CFE8004C4799 /* ReaderDetailHeaderView.swift */; }; @@ -4824,7 +4823,6 @@ FABB23942602FC2C00C8785C /* LoginEpilogueUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6158AC91ECDF518005FA441 /* LoginEpilogueUserInfo.swift */; }; FABB23962602FC2C00C8785C /* StatsTableFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 983DBBA922125DD300753988 /* StatsTableFooter.swift */; }; FABB23972602FC2C00C8785C /* BlogSyncFacade.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D239A21AE5A5FC0074768D /* BlogSyncFacade.m */; }; - FABB23982602FC2C00C8785C /* PrepublishingNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */; }; FABB23992602FC2C00C8785C /* UINavigationController+KeyboardFix.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D97C2F215CAF8D8009B44DD /* UINavigationController+KeyboardFix.m */; }; FABB239B2602FC2C00C8785C /* ExpandableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4034FDE92007C42400153B87 /* ExpandableCell.swift */; }; FABB239C2602FC2C00C8785C /* PreviewNonceHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5D0A64F23CC15A800B20D27 /* PreviewNonceHandler.swift */; }; @@ -7571,7 +7569,6 @@ 8B05D29223AA572A0063B9AA /* GutenbergMediaEditorImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GutenbergMediaEditorImage.swift; sourceTree = ""; }; 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepublishingHeaderView.swift; sourceTree = ""; }; 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Blog+Title.swift"; sourceTree = ""; }; - 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrepublishingNavigationController.swift; sourceTree = ""; }; 8B074A4F27AC3A64003A2EB8 /* BlogDashboardViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlogDashboardViewModel.swift; sourceTree = ""; }; 8B0CE7D02481CFE8004C4799 /* ReaderDetailHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderDetailHeaderView.swift; sourceTree = ""; }; 8B0CE7D22481CFF8004C4799 /* ReaderDetailHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ReaderDetailHeaderView.xib; sourceTree = ""; }; @@ -13914,7 +13911,6 @@ children = ( 8B0732E8242BA1F000E7FBD3 /* PrepublishingHeaderView.swift */, 8B0732EE242BF6EA00E7FBD3 /* Blog+Title.swift */, - 8B0732F1242BF97B00E7FBD3 /* PrepublishingNavigationController.swift */, 8B1CF00E2433902700578582 /* PasswordAlertController.swift */, ); path = "Prepublishing Nudge"; @@ -22097,7 +22093,6 @@ 85D239AE1AE5A5FC0074768D /* BlogSyncFacade.m in Sources */, 0CAE8EF22A9E9E8D0073EEB9 /* SiteMediaCollectionCell.swift in Sources */, 0CB54F572AEC320700582080 /* WordPressAppDelegate+PostCoordinatorDelegate.swift in Sources */, - 8B0732F3242BF99B00E7FBD3 /* PrepublishingNavigationController.swift in Sources */, 5D97C2F315CAF8D8009B44DD /* UINavigationController+KeyboardFix.m in Sources */, 4034FDEA2007C42400153B87 /* ExpandableCell.swift in Sources */, F5D0A65023CC15A800B20D27 /* PreviewNonceHandler.swift in Sources */, @@ -24937,7 +24932,6 @@ FABB23972602FC2C00C8785C /* BlogSyncFacade.m in Sources */, 083683DE2B4859BB00331ED0 /* NotificationsViewModel.swift in Sources */, 806BA11A2A492A2700052422 /* BlazeCampaignDetailsWebViewModel.swift in Sources */, - FABB23982602FC2C00C8785C /* PrepublishingNavigationController.swift in Sources */, 8384C64228AAC82600EABE26 /* KeychainUtils.swift in Sources */, FABB23992602FC2C00C8785C /* UINavigationController+KeyboardFix.m in Sources */, FABB239B2602FC2C00C8785C /* ExpandableCell.swift in Sources */, From d6d59b2aa393a44398369da2f3fed9b56ed191da Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 21:21:43 -0500 Subject: [PATCH 10/14] Update release notes --- RELEASE-NOTES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 25b2061e71e2..ecda82b9da22 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -1,6 +1,6 @@ 24.3 ----- - +* [**] Multiple pre-publishing sheet fixes and improvements [#22606] 24.2 ----- From be788a9b7a4b5791fcbba2d0a4636ada35763ee1 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 13 Feb 2024 21:26:56 -0500 Subject: [PATCH 11/14] Update UI tests --- .../Screens/Editor/AztecEditorScreen.swift | 2 +- .../Screens/Editor/EditorPostSettings.swift | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/WordPress/UITestsFoundation/Screens/Editor/AztecEditorScreen.swift b/WordPress/UITestsFoundation/Screens/Editor/AztecEditorScreen.swift index 41d8eebc52a3..a9a4c689e0cd 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/AztecEditorScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/AztecEditorScreen.swift @@ -259,7 +259,7 @@ public class AztecEditorScreen: ScreenObject { if FancyAlertComponent.isLoaded() { try FancyAlertComponent().acceptAlert() } else { - app.buttons["Publish Now"].tap() + app.buttons["Publish"].tap() } } diff --git a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift index d05a37823b64..0b5c7eb3b684 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift @@ -51,11 +51,16 @@ public class EditorPostSettings: ScreenObject { $0.buttons["Done"] } + private let backButtonGetter: (XCUIApplication) -> XCUIElement = { + $0.navigationBars.buttons.element(boundBy: 0) + } + var categoriesSection: XCUIElement { categoriesSectionGetter(app) } var chooseFromMediaButton: XCUIElement { chooseFromMediaButtonGetter(app) } var currentFeaturedImage: XCUIElement { currentFeaturedImageGetter(app) } var dateSelector: XCUIElement { dateSelectorGetter(app) } var doneButton: XCUIElement { doneButtonGetter(app) } + var backButton: XCUIElement { backButtonGetter(app) } var featuredImageButton: XCUIElement { featuredImageButtonGetter(app) } var firstCalendarDayButton: XCUIElement { firstCalendarDayButtonGetter(app) } var monthLabel: XCUIElement { monthLabelGetter(app) } @@ -155,7 +160,7 @@ public class EditorPostSettings: ScreenObject { firstCalendarDayButton.tapUntil(.selected, failureMessage: "First Day button not selected!") } - doneButton.tap() + backButton.tap() return self } From 9ffaa3a2277ce19b2074cc2c2b0e885c4bc63d5a Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Feb 2024 15:20:33 -0500 Subject: [PATCH 12/14] Update UI tests --- .../Post/PostEditor+MoreOptions.swift | 4 +++- .../PrepublishingViewController.swift | 2 +- .../Screens/Editor/BlockEditorScreen.swift | 2 +- .../Screens/Editor/EditorPostSettings.swift | 17 +++++++++-------- .../CategoriesComponent.swift | 7 ++++++- .../TagsComponent.swift | 7 ++++++- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift index add7d24a1869..1aaf85940132 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift @@ -11,9 +11,11 @@ extension PostEditor { settingsViewController = PostSettingsViewController(post: post) } settingsViewController.featuredImageDelegate = self as? FeaturedImageDelegate - settingsViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: .init(handler: { [weak self] _ in + let closeButton = UIBarButtonItem(systemItem: .close, primaryAction: .init(handler: { [weak self] _ in self?.navigationController?.dismiss(animated: true) })) + closeButton.accessibilityIdentifier = "close" + settingsViewController.navigationItem.leftBarButtonItem = closeButton let navigation = UINavigationController(rootViewController: settingsViewController) self.navigationController?.present(navigation, animated: true) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 3acedaf86e26..7d7637cc2ce1 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -60,7 +60,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource let publishButton: NUXButton = { let nuxButton = NUXButton() nuxButton.isPrimary = true - + nuxButton.accessibilityIdentifier = "publish" return nuxButton }() diff --git a/WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift b/WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift index 538bab40667b..b32c39651f3b 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/BlockEditorScreen.swift @@ -290,7 +290,7 @@ public class BlockEditorScreen: ScreenObject { } else if postType == .page && XCUIDevice.isPhone { postNowButton = app.scrollViews.buttons[action.rawValue] } else { - postNowButton = app.buttons["\(action.rawValue) Now"] + postNowButton = app.buttons["publish"] } waitForExistenceAndTap(postButton) diff --git a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift index 0b5c7eb3b684..0dc242d5837a 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift @@ -47,20 +47,20 @@ public class EditorPostSettings: ScreenObject { $0.buttons.containing(.staticText, identifier: "1").element } - private let doneButtonGetter: (XCUIApplication) -> XCUIElement = { - $0.buttons["Done"] + private let closeButtonGetter: (XCUIApplication) -> XCUIElement = { + $0.navigationBars.buttons["close"] } - private let backButtonGetter: (XCUIApplication) -> XCUIElement = { - $0.navigationBars.buttons.element(boundBy: 0) + private let backButtonGetter: (XCUIApplication) -> XCUIElement? = { + $0.navigationBars.lastMatch?.buttons.element(boundBy: 0) } var categoriesSection: XCUIElement { categoriesSectionGetter(app) } var chooseFromMediaButton: XCUIElement { chooseFromMediaButtonGetter(app) } var currentFeaturedImage: XCUIElement { currentFeaturedImageGetter(app) } var dateSelector: XCUIElement { dateSelectorGetter(app) } - var doneButton: XCUIElement { doneButtonGetter(app) } - var backButton: XCUIElement { backButtonGetter(app) } + var closeButton: XCUIElement { closeButtonGetter(app) } + var backButton: XCUIElement? { backButtonGetter(app) } var featuredImageButton: XCUIElement { featuredImageButtonGetter(app) } var firstCalendarDayButton: XCUIElement { firstCalendarDayButtonGetter(app) } var monthLabel: XCUIElement { monthLabelGetter(app) } @@ -136,7 +136,7 @@ public class EditorPostSettings: ScreenObject { @discardableResult public func closePostSettings() throws -> BlockEditorScreen { - navigateBack() + closeButton.tap() return try BlockEditorScreen() } @@ -160,7 +160,8 @@ public class EditorPostSettings: ScreenObject { firstCalendarDayButton.tapUntil(.selected, failureMessage: "First Day button not selected!") } - backButton.tap() + // Grab the top-most navigation bar + backButton?.tap() return self } diff --git a/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/CategoriesComponent.swift b/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/CategoriesComponent.swift index e077a1e9f6a0..7ab98353aa34 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/CategoriesComponent.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/CategoriesComponent.swift @@ -9,6 +9,11 @@ public class CategoriesComponent: ScreenObject { var categoriesList: XCUIElement { categoriesListGetter(app) } + var backButton: XCUIElement { + app.navigationBars["Post Categories"] + .buttons.element(boundBy: 0) + } + init(app: XCUIApplication = XCUIApplication()) throws { try super.init( expectedElementGetters: [ categoriesListGetter ], @@ -24,7 +29,7 @@ public class CategoriesComponent: ScreenObject { } func goBackToSettings() throws -> EditorPostSettings { - navigateBack() + backButton.tap() return try EditorPostSettings() } diff --git a/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/TagsComponent.swift b/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/TagsComponent.swift index bf6c9163e42f..66b18463d2e2 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/TagsComponent.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/EditorSettingsComponents/TagsComponent.swift @@ -9,6 +9,11 @@ public class TagsComponent: ScreenObject { var tagsField: XCUIElement { tagsFieldGetter(app) } + var backButton: XCUIElement { + app.navigationBars["Tags"] + .buttons.element(boundBy: 0) + } + init(app: XCUIApplication = XCUIApplication()) throws { try super.init( expectedElementGetters: [ tagsFieldGetter ], @@ -23,7 +28,7 @@ public class TagsComponent: ScreenObject { } func goBackToSettings() throws -> EditorPostSettings { - navigateBack() + backButton.tap() return try EditorPostSettings() } From a53ccccb9e160f7dd81f97db14c43772ed9f4c10 Mon Sep 17 00:00:00 2001 From: kean Date: Wed, 14 Feb 2024 22:07:39 -0500 Subject: [PATCH 13/14] Update UI tests --- .../Screens/Editor/EditorPostSettings.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift index 0dc242d5837a..8e025f64a20a 100644 --- a/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift +++ b/WordPress/UITestsFoundation/Screens/Editor/EditorPostSettings.swift @@ -160,8 +160,19 @@ public class EditorPostSettings: ScreenObject { firstCalendarDayButton.tapUntil(.selected, failureMessage: "First Day button not selected!") } - // Grab the top-most navigation bar - backButton?.tap() + if UIDevice.current.userInterfaceIdiom == .pad { + // Dismiss popover by tapping outside of it. There is a sheet covering + // the screen and a popover and both are "PopoverDismissRegion", so + // we need to find the first hittable. + app.otherElements.matching(identifier: "PopoverDismissRegion") + .allElementsBoundByIndex + .first(where: \.isHittable)? + .tap() + app.navigationBars["Publish"].buttons.element(boundBy: 0).tap() + } else { + app.navigationBars["Publish Date"].buttons.element(boundBy: 0).tap() + } + return self } From 5d4d3b31ed991a4f763aa5102189657d604da510 Mon Sep 17 00:00:00 2001 From: kean Date: Thu, 15 Feb 2024 07:54:40 -0500 Subject: [PATCH 14/14] Tiny design tweak --- .../Post/Prepublishing Nudge/PrepublishingHeaderView.swift | 2 +- .../Post/Prepublishing/PrepublishingViewController.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift index ccec7d762d89..61cd1e8a3953 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing Nudge/PrepublishingHeaderView.swift @@ -24,7 +24,7 @@ final class PrepublishingHeaderView: UIView { closeButton.configuration = { var configuration = UIButton.Configuration.plain() configuration.image = UIImage(systemName: "xmark.circle.fill") - configuration.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 14, bottom: 14, trailing: 12) + configuration.contentInsets = NSDirectionalEdgeInsets(top: 12, leading: 14, bottom: 14, trailing: 14) configuration.preferredSymbolConfigurationForImage = UIImage.SymbolConfiguration(paletteColors: [.secondaryLabel, .secondarySystemFill]) .applying(UIImage.SymbolConfiguration(font: WPStyleGuide.fontForTextStyle(.headline, fontWeight: .semibold))) return configuration diff --git a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift index 7d7637cc2ce1..e7d19341b279 100644 --- a/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Prepublishing/PrepublishingViewController.swift @@ -96,7 +96,7 @@ final class PrepublishingViewController: UIViewController, UITableViewDataSource } else { if let sheetController = navigationController.sheetPresentationController { if #available(iOS 16, *) { - sheetController.detents = [.custom { _ in 520 }, .large()] + sheetController.detents = [.custom { _ in 510 }, .large()] } else { sheetController.detents = [.medium(), .large()] }