From e4cb067538c34dcf2b83dcb967882512497f23a1 Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 30 Dec 2024 18:13:24 -0500 Subject: [PATCH 01/15] Remove unused LightNavigationController --- WordPress/Classes/Utility/Spotlight/SearchManager.swift | 2 +- .../Blog/Blog Details/BlogDetailsViewController.m | 2 +- .../BloggingRemindersNavigationController.swift | 2 +- .../Blog/My Site/Header/HomeSiteHeaderViewController.swift | 2 +- .../ViewRelated/Blog/Sharing/SharingAuthorizationHelper.m | 2 +- .../JetpackRestoreCompleteViewController.swift | 2 +- .../Notifications/ReplyTextView/ReplyTextView.swift | 2 +- .../People/Controllers/PeopleViewController.swift | 2 +- .../Post/Controllers/AbstractPostListViewController.swift | 2 +- .../Classes/ViewRelated/Post/PostEditor+MoreOptions.swift | 2 +- .../Post/Scheduling/LightNavigationController.swift | 7 ------- .../Post/Utils/PostNoticeNavigationCoordinator.swift | 2 +- .../Post/Utils/PostNoticePublishSuccessView.swift | 2 +- .../ReaderPostActions/ReaderVisitSiteAction.swift | 2 +- .../Reader/Detail/ReaderDetailCoordinator.swift | 2 +- WordPress/WordPress.xcodeproj/project.pbxproj | 4 ---- .../FullScreenCommentReplyViewControllerTests.swift | 2 +- 17 files changed, 15 insertions(+), 26 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Post/Scheduling/LightNavigationController.swift diff --git a/WordPress/Classes/Utility/Spotlight/SearchManager.swift b/WordPress/Classes/Utility/Spotlight/SearchManager.swift index eeb41704e412..52f20c19f3be 100644 --- a/WordPress/Classes/Utility/Spotlight/SearchManager.swift +++ b/WordPress/Classes/Utility/Spotlight/SearchManager.swift @@ -458,7 +458,7 @@ fileprivate extension SearchManager { let controller = PreviewWebKitViewController(post: apost, source: "spotlight_preview_post") controller.trackOpenEvent() - let navWrapper = LightNavigationController(rootViewController: controller) + let navWrapper = UINavigationController(rootViewController: controller) let rootViewController = RootViewCoordinator.sharedPresenter.rootViewController if rootViewController.traitCollection.userInterfaceIdiom == .pad { navWrapper.modalPresentationStyle = .fullScreen diff --git a/WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m b/WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m index ab41fbca01b8..33a2f1bca520 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Blog Details/BlogDetailsViewController.m @@ -1939,7 +1939,7 @@ - (void)showViewSiteFromSource:(BlogDetailsNavigationSource)source source:@"my_site_view_site" withDeviceModes:true onClose:nil]; - LightNavigationController *navController = [[LightNavigationController alloc] initWithRootViewController:webViewController]; + UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:webViewController]; if (self.traitCollection.userInterfaceIdiom == UIUserInterfaceIdiomPad) { navController.modalPresentationStyle = UIModalPresentationFullScreen; } diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift b/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift index df093f371e63..33d9562ac586 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift +++ b/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift @@ -5,7 +5,7 @@ protocol ChildDrawerPositionable { var preferredDrawerPosition: DrawerPosition { get } } -class BloggingRemindersNavigationController: LightNavigationController { +class BloggingRemindersNavigationController: UINavigationController { typealias DismissClosure = () -> Void diff --git a/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController.swift b/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController.swift index 2d9150326fbb..ff200d4d21a0 100644 --- a/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/My Site/Header/HomeSiteHeaderViewController.swift @@ -255,7 +255,7 @@ extension HomeSiteHeaderViewController { onClose: nil ) - let navigationController = LightNavigationController(rootViewController: webViewController) + let navigationController = UINavigationController(rootViewController: webViewController) if traitCollection.userInterfaceIdiom == .pad { navigationController.modalPresentationStyle = .fullScreen diff --git a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingAuthorizationHelper.m b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingAuthorizationHelper.m index 30436b269ca2..0b64b9e8aef6 100644 --- a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingAuthorizationHelper.m +++ b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingAuthorizationHelper.m @@ -91,7 +91,7 @@ - (void)authorizeWithConnectionURL:(NSURL *)connectionURL { SharingAuthorizationWebViewController *webViewController = [[SharingAuthorizationWebViewController alloc] initWith:self.publicizeService url:connectionURL for:self.blog delegate:self]; - self.navController = [[LightNavigationController alloc] initWithRootViewController:webViewController]; + self.navController = [[UINavigationController alloc] initWithRootViewController:webViewController]; self.navController.modalPresentationStyle = UIModalPresentationFormSheet; [self.viewController presentViewController:self.navController animated:YES completion:nil]; } diff --git a/WordPress/Classes/ViewRelated/Jetpack/Jetpack Restore/Restore Complete/JetpackRestoreCompleteViewController.swift b/WordPress/Classes/ViewRelated/Jetpack/Jetpack Restore/Restore Complete/JetpackRestoreCompleteViewController.swift index afb44f0f80a1..7075dbfcd052 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Jetpack Restore/Restore Complete/JetpackRestoreCompleteViewController.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Jetpack Restore/Restore Complete/JetpackRestoreCompleteViewController.swift @@ -54,7 +54,7 @@ class JetpackRestoreCompleteViewController: BaseRestoreCompleteViewController { } let webVC = WebViewControllerFactory.controller(url: homeURL, source: "jetpack_restore_complete") - let navigationVC = LightNavigationController(rootViewController: webVC) + let navigationVC = UINavigationController(rootViewController: webVC) self.present(navigationVC, animated: true) } diff --git a/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.swift b/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.swift index aada63071618..003e65a7ff59 100644 --- a/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.swift +++ b/WordPress/Classes/ViewRelated/Notifications/ReplyTextView/ReplyTextView.swift @@ -216,7 +216,7 @@ import Gridicons self.resignFirstResponder() - let navController = LightNavigationController(rootViewController: editViewController) + let navController = UINavigationController(rootViewController: editViewController) rootViewController.present(navController, animated: true) } diff --git a/WordPress/Classes/ViewRelated/People/Controllers/PeopleViewController.swift b/WordPress/Classes/ViewRelated/People/Controllers/PeopleViewController.swift index f3d6ccca3ab7..a2f689990ebb 100644 --- a/WordPress/Classes/ViewRelated/People/Controllers/PeopleViewController.swift +++ b/WordPress/Classes/ViewRelated/People/Controllers/PeopleViewController.swift @@ -188,7 +188,7 @@ class PeopleViewController: UITableViewController { self?.refreshPeople() } let viewController = WebKitViewController(configuration: configuration) - let navWrapper = LightNavigationController(rootViewController: viewController) + let navWrapper = UINavigationController(rootViewController: viewController) navigationController?.present(navWrapper, animated: true) } } diff --git a/WordPress/Classes/ViewRelated/Post/Controllers/AbstractPostListViewController.swift b/WordPress/Classes/ViewRelated/Post/Controllers/AbstractPostListViewController.swift index 020e21f3b4e3..8fa79f8f1282 100644 --- a/WordPress/Classes/ViewRelated/Post/Controllers/AbstractPostListViewController.swift +++ b/WordPress/Classes/ViewRelated/Post/Controllers/AbstractPostListViewController.swift @@ -664,7 +664,7 @@ class AbstractPostListViewController: UIViewController, // NOTE: We'll set the title to match the title of the View action button. // If the button title changes we should also update the title here. controller.navigationItem.title = NSLocalizedString("View", comment: "Verb. The screen title shown when viewing a post inside the app.") - let navWrapper = LightNavigationController(rootViewController: controller) + let navWrapper = UINavigationController(rootViewController: controller) if navigationController?.traitCollection.userInterfaceIdiom == .pad { navWrapper.modalPresentationStyle = .fullScreen } diff --git a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift index 76000b4302af..9bae8164b833 100644 --- a/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift +++ b/WordPress/Classes/ViewRelated/Post/PostEditor+MoreOptions.swift @@ -87,7 +87,7 @@ extension PostEditor { previewController = PreviewWebKitViewController(post: self.post, source: "edit_post_more_preview") } previewController.trackOpenEvent() - let navWrapper = LightNavigationController(rootViewController: previewController) + let navWrapper = UINavigationController(rootViewController: previewController) if self.navigationController?.traitCollection.userInterfaceIdiom == .pad { navWrapper.modalPresentationStyle = .fullScreen } diff --git a/WordPress/Classes/ViewRelated/Post/Scheduling/LightNavigationController.swift b/WordPress/Classes/ViewRelated/Post/Scheduling/LightNavigationController.swift deleted file mode 100644 index 6a8937bf1c91..000000000000 --- a/WordPress/Classes/ViewRelated/Post/Scheduling/LightNavigationController.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -// TODO: remove - -// A Navigation Controller with a light navigation bar style -class LightNavigationController: UINavigationController { -} diff --git a/WordPress/Classes/ViewRelated/Post/Utils/PostNoticeNavigationCoordinator.swift b/WordPress/Classes/ViewRelated/Post/Utils/PostNoticeNavigationCoordinator.swift index ad536f6b5194..8168ed23bf60 100644 --- a/WordPress/Classes/ViewRelated/Post/Utils/PostNoticeNavigationCoordinator.swift +++ b/WordPress/Classes/ViewRelated/Post/Utils/PostNoticeNavigationCoordinator.swift @@ -28,7 +28,7 @@ class PostNoticeNavigationCoordinator { controller.trackOpenEvent() controller.navigationItem.title = NSLocalizedString("View", comment: "Verb. The screen title shown when viewing a post inside the app.") - let navigationController = LightNavigationController(rootViewController: controller) + let navigationController = UINavigationController(rootViewController: controller) if presenter.traitCollection.userInterfaceIdiom == .pad { navigationController.modalPresentationStyle = .fullScreen } diff --git a/WordPress/Classes/ViewRelated/Post/Utils/PostNoticePublishSuccessView.swift b/WordPress/Classes/ViewRelated/Post/Utils/PostNoticePublishSuccessView.swift index 6b7e22e75f8f..0b3c259ed034 100644 --- a/WordPress/Classes/ViewRelated/Post/Utils/PostNoticePublishSuccessView.swift +++ b/WordPress/Classes/ViewRelated/Post/Utils/PostNoticePublishSuccessView.swift @@ -117,7 +117,7 @@ struct PostNoticePublishSuccessView: View { WPAnalytics.track(.postEpilogueView) let controller = PreviewWebKitViewController(post: post, source: "edit_post_preview") controller.trackOpenEvent() - let navWrapper = LightNavigationController(rootViewController: controller) + let navWrapper = UINavigationController(rootViewController: controller) presenter.present(navWrapper, animated: true) } diff --git a/WordPress/Classes/ViewRelated/Reader/Controllers/ReaderPostActions/ReaderVisitSiteAction.swift b/WordPress/Classes/ViewRelated/Reader/Controllers/ReaderPostActions/ReaderVisitSiteAction.swift index 0e2cb91c8c29..ddad644dfeb6 100644 --- a/WordPress/Classes/ViewRelated/Reader/Controllers/ReaderPostActions/ReaderVisitSiteAction.swift +++ b/WordPress/Classes/ViewRelated/Reader/Controllers/ReaderPostActions/ReaderVisitSiteAction.swift @@ -14,7 +14,7 @@ final class ReaderVisitSiteAction { configuration.authenticate(account: account) } let controller = WebViewControllerFactory.controller(configuration: configuration, source: "reader_visit_site") - let navController = LightNavigationController(rootViewController: controller) + let navController = UINavigationController(rootViewController: controller) origin.present(navController, animated: true) WPAnalytics.trackReader(.readerArticleVisited) } diff --git a/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailCoordinator.swift b/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailCoordinator.swift index c037dfef9f3a..607ff17c6c8a 100644 --- a/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailCoordinator.swift +++ b/WordPress/Classes/ViewRelated/Reader/Detail/ReaderDetailCoordinator.swift @@ -573,7 +573,7 @@ class ReaderDetailCoordinator { configuration.authenticateWithDefaultAccount() configuration.addsWPComReferrer = true let controller = WebViewControllerFactory.controller(configuration: configuration, source: "reader_detail") - let navController = LightNavigationController(rootViewController: controller) + let navController = UINavigationController(rootViewController: controller) viewController?.present(navController, animated: true) } diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 2d1bfab4901d..927371beb713 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -3414,7 +3414,6 @@ "ViewRelated/Aztec/Extensions/TextList+WordPress.swift", ViewRelated/Aztec/Processors/ImgUploadProcessor.swift, ViewRelated/Cells/WPReusableTableViewCells.swift, - ViewRelated/Post/Scheduling/LightNavigationController.swift, ViewRelated/Tools/TableViewKeyboardObserver.swift, ViewRelated/Views/NoResults.storyboard, ViewRelated/Views/NoResultsViewController.swift, @@ -3454,7 +3453,6 @@ "ViewRelated/Aztec/Extensions/TextList+WordPress.swift", ViewRelated/Aztec/Processors/ImgUploadProcessor.swift, ViewRelated/Cells/WPReusableTableViewCells.swift, - ViewRelated/Post/Scheduling/LightNavigationController.swift, ViewRelated/Tools/TableViewKeyboardObserver.swift, ViewRelated/Views/NoResults.storyboard, ViewRelated/Views/NoResultsViewController.swift, @@ -3585,7 +3583,6 @@ "ViewRelated/Aztec/Extensions/TextList+WordPress.swift", ViewRelated/Aztec/Processors/ImgUploadProcessor.swift, ViewRelated/Cells/WPReusableTableViewCells.swift, - ViewRelated/Post/Scheduling/LightNavigationController.swift, ViewRelated/Tools/TableViewKeyboardObserver.swift, ViewRelated/Views/NoResults.storyboard, ViewRelated/Views/NoResultsViewController.swift, @@ -3623,7 +3620,6 @@ "ViewRelated/Aztec/Extensions/TextList+WordPress.swift", ViewRelated/Aztec/Processors/ImgUploadProcessor.swift, ViewRelated/Cells/WPReusableTableViewCells.swift, - ViewRelated/Post/Scheduling/LightNavigationController.swift, ViewRelated/Tools/TableViewKeyboardObserver.swift, ViewRelated/Views/NoResults.storyboard, ViewRelated/Views/NoResultsViewController.swift, diff --git a/WordPress/WordPressTest/Comments/Controllers/FullScreenCommentReplyViewControllerTests.swift b/WordPress/WordPressTest/Comments/Controllers/FullScreenCommentReplyViewControllerTests.swift index 1e839c8ef615..7f04a1ecec65 100644 --- a/WordPress/WordPressTest/Comments/Controllers/FullScreenCommentReplyViewControllerTests.swift +++ b/WordPress/WordPressTest/Comments/Controllers/FullScreenCommentReplyViewControllerTests.swift @@ -136,7 +136,7 @@ class FullScreenCommentReplyViewControllerTests: CoreDataTestCase { /// - inWindow: The window instance you want to load it in private func load(_ controller: UIViewController, inWindow: UIWindow) { inWindow.addSubview(controller.view) - inWindow.rootViewController = LightNavigationController(rootViewController: controller) + inWindow.rootViewController = UINavigationController(rootViewController: controller) inWindow.makeKeyAndVisible() controller.beginAppearanceTransition(true, animated: false) RunLoop.current.run(until: Date()) From dfcb04a96c1d6f3a0449237b7a5ec55e5463be1e Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 30 Dec 2024 18:37:11 -0500 Subject: [PATCH 02/15] Remove BottomSheetViewController usage from BloggingReminders flow --- .../Extensions/UIButton+Extensions.swift | 13 ++ .../BloggingRemindersScheduler.swift | 2 +- .../BloggingRemindersAnimator.swift | 67 ---------- .../BloggingRemindersFlow.swift | 87 ------------- ...loggingRemindersNavigationController.swift | 123 ------------------ .../BloggingRemindersActions.swift | 2 + .../BloggingRemindersFlow.swift | 78 +++++++++++ ...emindersFlowCompletionViewController.swift | 24 ---- ...gingRemindersFlowIntroViewController.swift | 77 +++-------- ...gRemindersFlowSettingsViewController.swift | 21 +-- ...loggingRemindersNavigationController.swift | 32 +++++ ...ingRemindersPushPromptViewController.swift | 14 -- .../BloggingRemindersTracker.swift | 0 .../CalendarDayToggleButton.swift | 0 ...loggingRemindersTimeSelectionButton.swift} | 2 +- .../BloggingRemindersTimeSelectionView.swift} | 6 +- ...emindersTimeSelectionViewController.swift} | 32 +---- .../JetpackOverlayViewController.swift | 6 - 18 files changed, 154 insertions(+), 432 deletions(-) delete mode 100644 WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersAnimator.swift delete mode 100644 WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlow.swift delete mode 100644 WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersActions.swift (97%) create mode 100644 WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersFlowCompletionViewController.swift (92%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersFlowIntroViewController.swift (67%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersFlowSettingsViewController.swift (97%) create mode 100644 WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersPushPromptViewController.swift (96%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/BloggingRemindersTracker.swift (100%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders => BloggingReminders}/CalendarDayToggleButton.swift (100%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders/Time Selector/TimeSelectionButton.swift => BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionButton.swift} (97%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders/Time Selector/TimeSelectionView.swift => BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift} (91%) rename WordPress/Classes/ViewRelated/Blog/{Blogging Reminders/Time Selector/TimeSelectionViewController.swift => BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift} (65%) diff --git a/WordPress/Classes/Extensions/UIButton+Extensions.swift b/WordPress/Classes/Extensions/UIButton+Extensions.swift index 68b46e1ee49e..2194627639e6 100644 --- a/WordPress/Classes/Extensions/UIButton+Extensions.swift +++ b/WordPress/Classes/Extensions/UIButton+Extensions.swift @@ -31,3 +31,16 @@ extension UIButton { }()) } } + +extension UIButton.Configuration { + static func primary() -> UIButton.Configuration { + var configuration = UIButton.Configuration.borderedProminent() + configuration.titleTextAttributesTransformer = .init { attributes in + var attributes = attributes + attributes.font = UIFont.preferredFont(forTextStyle: .headline) + return attributes + } + configuration.buttonSize = .large + return configuration + } +} diff --git a/WordPress/Classes/Utility/Blogging Reminders/BloggingRemindersScheduler.swift b/WordPress/Classes/Utility/Blogging Reminders/BloggingRemindersScheduler.swift index d083a0e054e6..63c31026a227 100644 --- a/WordPress/Classes/Utility/Blogging Reminders/BloggingRemindersScheduler.swift +++ b/WordPress/Classes/Utility/Blogging Reminders/BloggingRemindersScheduler.swift @@ -17,7 +17,7 @@ extension InteractiveNotificationsManager: PushNotificationAuthorizer { /// Main interface for scheduling blogging reminders /// -class BloggingRemindersScheduler { +final class BloggingRemindersScheduler { // MARK: - Convenience Typealiases diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersAnimator.swift b/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersAnimator.swift deleted file mode 100644 index 978538eef3dc..000000000000 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersAnimator.swift +++ /dev/null @@ -1,67 +0,0 @@ -/// A transition animator that moves in the pushed view controller horizontally. -/// Does not handle the pop animation since the BloggingReminders setup flow does not allow to navigate back. -class BloggingRemindersAnimator: NSObject, UIViewControllerAnimatedTransitioning { - - var popStyle = false - - private static let animationDuration: TimeInterval = 0.2 - private static let sourceEndFrameOffset: CGFloat = -60.0 - - func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { - return Self.animationDuration - } - - func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { - - guard !popStyle else { - animatePop(using: transitionContext) - return - } - - guard let sourceViewController = - transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), - let destinationViewController = - transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { - return - } - // final position of the destination view - let destinationEndFrame = transitionContext.finalFrame(for: destinationViewController) - // final position of the source view - let sourceEndFrame = transitionContext.initialFrame(for: sourceViewController).offsetBy(dx: Self.sourceEndFrameOffset, dy: .zero) - - // initial position of the destination view - let destinationStartFrame = destinationEndFrame.offsetBy(dx: destinationEndFrame.width, dy: .zero) - destinationViewController.view.frame = destinationStartFrame - - transitionContext.containerView.insertSubview(destinationViewController.view, aboveSubview: sourceViewController.view) - - UIView.animate(withDuration: transitionDuration(using: transitionContext), - animations: { - destinationViewController.view.frame = destinationEndFrame - sourceViewController.view.frame = sourceEndFrame - }, completion: {_ in - transitionContext.completeTransition(true) - }) - } - - func animatePop(using transitionContext: UIViewControllerContextTransitioning) { - guard let sourceViewController = - transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from), - let destinationViewController = - transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to) else { - return - } - let destinationEndFrame = transitionContext.finalFrame(for: destinationViewController) - let destinationStartFrame = destinationEndFrame.offsetBy(dx: Self.sourceEndFrameOffset, dy: .zero) - destinationViewController.view.frame = destinationStartFrame - transitionContext.containerView.insertSubview(destinationViewController.view, belowSubview: sourceViewController.view) - - UIView.animate(withDuration: transitionDuration(using: transitionContext), - animations: { - destinationViewController.view.frame = destinationEndFrame - sourceViewController.view.transform = sourceViewController.view.transform.translatedBy(x: sourceViewController.view.frame.width, y: 0) - }, completion: {_ in - transitionContext.completeTransition(true) - }) - } -} diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlow.swift b/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlow.swift deleted file mode 100644 index 582380d5db83..000000000000 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlow.swift +++ /dev/null @@ -1,87 +0,0 @@ -import Foundation -import WordPressUI - -class BloggingRemindersFlow { - - typealias DismissClosure = () -> Void - - static func present(from viewController: UIViewController, - for blog: Blog, - source: BloggingRemindersTracker.FlowStartSource, - alwaysShow: Bool = true, - delegate: BloggingRemindersFlowDelegate? = nil, - onDismiss: DismissClosure? = nil) { - - guard blog.areBloggingRemindersAllowed() else { - return - } - - guard alwaysShow || !hasShownWeeklyRemindersFlow(for: blog) else { - return - } - - let blogType: BloggingRemindersTracker.BlogType = blog.isHostedAtWPcom ? .wpcom : .selfHosted - - let tracker = BloggingRemindersTracker(blogType: blogType) - tracker.flowStarted(source: source) - - let flowStartViewController = makeStartViewController(for: blog, - tracker: tracker, - source: source, - delegate: delegate) - let navigationController = BloggingRemindersNavigationController( - rootViewController: flowStartViewController, - onDismiss: { - NoticesDispatch.unlock() - onDismiss?() - }) - - let bottomSheet = BottomSheetViewController(childViewController: navigationController, - customHeaderSpacing: 0) - - NoticesDispatch.lock() - bottomSheet.show(from: viewController) - setHasShownWeeklyRemindersFlow(for: blog) - } - - /// if the flow has never been seen, it starts with the intro. Otherwise it starts with the calendar settings - private static func makeStartViewController(for blog: Blog, - tracker: BloggingRemindersTracker, - source: BloggingRemindersTracker.FlowStartSource, - delegate: BloggingRemindersFlowDelegate? = nil) -> UIViewController { - - guard hasShownWeeklyRemindersFlow(for: blog) else { - return BloggingRemindersFlowIntroViewController(for: blog, - tracker: tracker, - source: source, - delegate: delegate) - } - - return (try? BloggingRemindersFlowSettingsViewController(for: blog, tracker: tracker, delegate: delegate)) ?? - BloggingRemindersFlowIntroViewController(for: blog, tracker: tracker, source: source, delegate: delegate) - } - - // MARK: - Weekly reminders flow presentation status - // - // stores a key for each blog in UserDefaults to determine if - // the flow was presented for the given blog. - private static func hasShownWeeklyRemindersFlow(for blog: Blog) -> Bool { - UserPersistentStoreFactory.instance().bool(forKey: weeklyRemindersKey(for: blog)) - } - - static func setHasShownWeeklyRemindersFlow(for blog: Blog) { - UserPersistentStoreFactory.instance().set(true, forKey: weeklyRemindersKey(for: blog)) - } - - private static func weeklyRemindersKey(for blog: Blog) -> String { - // weekly reminders key prefix - let prefix = "blogging-reminder-weekly-" - return prefix + blog.objectID.uriRepresentation().absoluteString - } - - /// By making this private we ensure this can't be instantiated. - /// - private init() { - assertionFailure() - } -} diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift b/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift deleted file mode 100644 index 33d9562ac586..000000000000 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersNavigationController.swift +++ /dev/null @@ -1,123 +0,0 @@ -import UIKit -import WordPressUI - -protocol ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { get } -} - -class BloggingRemindersNavigationController: UINavigationController { - - typealias DismissClosure = () -> Void - - private let onDismiss: DismissClosure? - - required init(rootViewController: UIViewController, onDismiss: DismissClosure? = nil) { - self.onDismiss = onDismiss - - super.init(rootViewController: rootViewController) - - delegate = self - setNavigationBarHidden(true, animated: false) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - - if isBeingDismissedDirectlyOrByAncestor() { - onDismiss?() - } - } - - override var supportedInterfaceOrientations: UIInterfaceOrientationMask { - return .portrait - } - - 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) - - updateDrawerPosition() - } - - override func popViewController(animated: Bool) -> UIViewController? { - let viewController = super.popViewController(animated: animated) - - updateDrawerPosition() - - return viewController - } - - private func updateDrawerPosition() { - if let bottomSheet = self.parent as? BottomSheetViewController, - let presentedVC = bottomSheet.presentedVC, - let currentVC = topViewController as? ChildDrawerPositionable { - presentedVC.transition(to: currentVC.preferredDrawerPosition) - } - } -} - -// MARK: - DrawerPresentable - -extension BloggingRemindersNavigationController: DrawerPresentable { - var allowsUserTransition: Bool { - return false - } - - var allowsDragToDismiss: Bool { - return true - } - - var allowsTapToDismiss: Bool { - return true - } - - var expandedHeight: DrawerHeight { - return .maxHeight - } - - var collapsedHeight: DrawerHeight { - if let viewController = viewControllers.last as? DrawerPresentable { - return viewController.collapsedHeight - } - - return .intrinsicHeight - } - - func handleDismiss() { - (children.last as? DrawerPresentable)?.handleDismiss() - } -} - -// MARK: - NavigationControllerDelegate - -extension BloggingRemindersNavigationController: UINavigationControllerDelegate { - - /// This implementation uses the custom `BloggingRemindersAnimator` to improve screen transitions - /// in the blogging reminders setup flow. - func navigationController(_ navigationController: UINavigationController, - animationControllerFor operation: UINavigationController.Operation, - from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { - - let animator = BloggingRemindersAnimator() - animator.popStyle = (operation == .pop) - - return animator - } -} diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersActions.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersActions.swift similarity index 97% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersActions.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersActions.swift index b1105e99422a..22b0ac2d858b 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersActions.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersActions.swift @@ -1,3 +1,5 @@ +import UIKit + /// Conform to this protocol to implement common actions for the blogging reminders flow protocol BloggingRemindersActions: UIViewController { func dismiss(from button: BloggingRemindersTracker.Button, diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift new file mode 100644 index 000000000000..622047076dc7 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift @@ -0,0 +1,78 @@ +import UIKit +import WordPressUI + +final class BloggingRemindersFlow { + static func present( + from presentingViewController: UIViewController, + for blog: Blog, + source: BloggingRemindersTracker.FlowStartSource, + alwaysShow: Bool = true, + delegate: BloggingRemindersFlowDelegate? = nil, + onDismiss: (() -> Void)? = nil + ) { + guard blog.areBloggingRemindersAllowed() else { + return + } + + guard alwaysShow || !hasShownWeeklyRemindersFlow(for: blog) else { + return + } + + let blogType: BloggingRemindersTracker.BlogType = blog.isHostedAtWPcom ? .wpcom : .selfHosted + + let tracker = BloggingRemindersTracker(blogType: blogType) + tracker.flowStarted(source: source) + + let showSettings = { [weak presentingViewController] in + do { + let settingsVC = try BloggingRemindersFlowSettingsViewController(for: blog, tracker: tracker, delegate: delegate) + let navigationController = BloggingRemindersNavigationController(rootViewController: settingsVC, onDismiss: { + NoticesDispatch.unlock() + onDismiss?() + }) + NoticesDispatch.lock() + presentingViewController?.present(navigationController, animated: true) + } catch { + wpAssertionFailure("Could not instantiate the blogging reminders settings VC", userInfo: ["error": "\(error)"]) + } + } + + if hasShownWeeklyRemindersFlow(for: blog) { + showSettings() + } else { + let introVC = BloggingRemindersFlowIntroViewController(for: blog, tracker: tracker, source: source) { [weak presentingViewController] in + presentingViewController?.dismiss(animated: true) { + showSettings() + } + } + introVC.sheetPresentationController?.detents = [.medium()] + presentingViewController.present(introVC, animated: true) + } + + setHasShownWeeklyRemindersFlow(for: blog) + } + + // MARK: - Weekly reminders flow presentation status + // + // stores a key for each blog in UserDefaults to determine if + // the flow was presented for the given blog. + private static func hasShownWeeklyRemindersFlow(for blog: Blog) -> Bool { + UserPersistentStoreFactory.instance().bool(forKey: weeklyRemindersKey(for: blog)) + } + + static func setHasShownWeeklyRemindersFlow(for blog: Blog) { + UserPersistentStoreFactory.instance().set(true, forKey: weeklyRemindersKey(for: blog)) + } + + private static func weeklyRemindersKey(for blog: Blog) -> String { + // weekly reminders key prefix + let prefix = "blogging-reminder-weekly-" + return prefix + blog.objectID.uriRepresentation().absoluteString + } + + /// By making this private we ensure this can't be instantiated. + /// + private init() { + assertionFailure() + } +} diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowCompletionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift similarity index 92% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowCompletionViewController.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift index 63a439c3f8ab..c71158b053ff 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowCompletionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift @@ -121,22 +121,12 @@ class BloggingRemindersFlowCompletionViewController: UIViewController { } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - calculatePreferredContentSize() - } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) hintLabel.isHidden = traitCollection.preferredContentSizeCategory.isAccessibilityCategory } - func calculatePreferredContentSize() { - let size = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height) - preferredContentSize = view.systemLayoutSizeFitting(size) - } - // MARK: - View Configuration private func configureStackView() { @@ -223,20 +213,6 @@ extension BloggingRemindersFlowCompletionViewController: BloggingRemindersAction } } -// MARK: - DrawerPresentable - -extension BloggingRemindersFlowCompletionViewController: DrawerPresentable { - var collapsedHeight: DrawerHeight { - return .intrinsicHeight - } -} - -extension BloggingRemindersFlowCompletionViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - return .collapsed - } -} - // MARK: - Constants private enum TextContent { diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowIntroViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift similarity index 67% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowIntroViewController.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift index 36666edd5eb8..31447713322e 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowIntroViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift @@ -1,7 +1,7 @@ import UIKit import WordPressUI -class BloggingRemindersFlowIntroViewController: UIViewController { +final class BloggingRemindersFlowIntroViewController: UIViewController { // MARK: - Subviews @@ -43,37 +43,33 @@ class BloggingRemindersFlowIntroViewController: UIViewController { return label }() - private lazy var getStartedButton: UIButton = { - let button = FancyButton() - button.isPrimary = true - button.setTitle(Strings.introButtonTitle, for: .normal) - button.addTarget(self, action: #selector(getStartedTapped), for: .touchUpInside) - return button - }() + private lazy var buttonNext: UIButton = { + var configuration = UIButton.Configuration.primary() + configuration.title = Strings.introButtonTitle - // MARK: - Initializers + return UIButton(configuration: configuration, primaryAction: .init { [weak self] _ in + self?.buttonGetStartedTapped() + }) + }() private let blog: Blog private let tracker: BloggingRemindersTracker private let source: BloggingRemindersTracker.FlowStartSource - private weak var delegate: BloggingRemindersFlowDelegate? + private let onNextTapped: () -> Void init(for blog: Blog, tracker: BloggingRemindersTracker, source: BloggingRemindersTracker.FlowStartSource, - delegate: BloggingRemindersFlowDelegate? = nil) { + onNextTapped: @escaping () -> Void) { self.blog = blog self.tracker = tracker self.source = source - self.delegate = delegate + self.onNextTapped = onNextTapped super.init(nibName: nil, bundle: nil) } required init?(coder: NSCoder) { - // This VC is designed to be instantiated programmatically. If we ever need to initialize this VC - // from a coder, we can implement support for it - but I don't think it's necessary right now. - // - diegoreymendez fatalError("Use init(tracker:) instead") } @@ -105,22 +101,6 @@ class BloggingRemindersFlowIntroViewController: UIViewController { } } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - calculatePreferredContentSize() - } - - private func calculatePreferredContentSize() { - let size = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height) - preferredContentSize = view.systemLayoutSizeFitting(size) - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - view.setNeedsLayout() - } - // MARK: - View Configuration private func configureStackView() { @@ -129,7 +109,7 @@ class BloggingRemindersFlowIntroViewController: UIViewController { imageView, titleLabel, promptLabel, - getStartedButton + buttonNext ]) stackView.setCustomSpacing(Metrics.afterPromptSpacing, after: promptLabel) } @@ -141,48 +121,23 @@ class BloggingRemindersFlowIntroViewController: UIViewController { stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: Metrics.edgeMargins.top), stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeBottomAnchor, constant: -Metrics.edgeMargins.bottom), - getStartedButton.heightAnchor.constraint(greaterThanOrEqualToConstant: Metrics.getStartedButtonHeight), - getStartedButton.widthAnchor.constraint(equalTo: stackView.widthAnchor), + buttonNext.heightAnchor.constraint(greaterThanOrEqualToConstant: Metrics.getStartedButtonHeight), + buttonNext.widthAnchor.constraint(equalTo: stackView.widthAnchor), ]) } - @objc private func getStartedTapped() { + private func buttonGetStartedTapped() { tracker.buttonPressed(button: .continue, screen: .main) - - do { - let flowSettingsViewController = try BloggingRemindersFlowSettingsViewController(for: blog, tracker: tracker, delegate: delegate) - - navigationController?.pushViewController(flowSettingsViewController, animated: true) - } catch { - DDLogError("Could not instantiate the blogging reminders settings VC: \(error.localizedDescription)") - dismiss(animated: true, completion: nil) - } + onNextTapped() } } extension BloggingRemindersFlowIntroViewController: BloggingRemindersActions { - @objc private func dismissTapped() { dismiss(from: .dismiss, screen: .main, tracker: tracker) } } -// MARK: - DrawerPresentable - -extension BloggingRemindersFlowIntroViewController: DrawerPresentable { - var collapsedHeight: DrawerHeight { - return .intrinsicHeight - } -} - -// MARK: - ChildDrawerPositionable - -extension BloggingRemindersFlowIntroViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - return .collapsed - } -} - // MARK: - Constants private enum Strings { diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowSettingsViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift similarity index 97% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowSettingsViewController.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift index 17af112e0157..22f605d939b9 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersFlowSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift @@ -6,7 +6,7 @@ protocol BloggingRemindersFlowDelegate: AnyObject { func didSetUpBloggingReminders() } -class BloggingRemindersFlowSettingsViewController: UIViewController { +final class BloggingRemindersFlowSettingsViewController: UIViewController { // MARK: - Subviews @@ -110,8 +110,8 @@ class BloggingRemindersFlowSettingsViewController: UIViewController { makeDivider() }() - private lazy var timeSelectionButton: TimeSelectionButton = { - let button = TimeSelectionButton(selectedTime: scheduledTime.toLocalTime()) + private lazy var timeSelectionButton: BloggingRemindersTimeSelectionButton = { + let button = BloggingRemindersTimeSelectionButton(selectedTime: scheduledTime.toLocalTime()) button.isUserInteractionEnabled = true button.translatesAutoresizingMaskIntoConstraints = false button.addTarget(self, action: #selector(navigateToTimePicker), for: .touchUpInside) @@ -408,8 +408,7 @@ class BloggingRemindersFlowSettingsViewController: UIViewController { private extension BloggingRemindersFlowSettingsViewController { func pushTimeSelectionViewController() { - let viewController = TimeSelectionViewController(scheduledTime: scheduler.scheduledTime(for: blog), - tracker: tracker) { [weak self] date in + let viewController = BloggingRemindersTimeSelectionViewController(scheduledTime: scheduler.scheduledTime(for: blog), tracker: tracker) { [weak self] date in self?.scheduledTime = date self?.timeSelectionButton.setSelectedTime(date.toLocalTime()) self?.refreshNextButton() @@ -653,18 +652,6 @@ extension BloggingRemindersFlowSettingsViewController: BloggingRemindersActions } } -extension BloggingRemindersFlowSettingsViewController: DrawerPresentable { - var collapsedHeight: DrawerHeight { - return .maxHeight - } -} - -extension BloggingRemindersFlowSettingsViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - return .expanded - } -} - // MARK: - Blogging Prompts Helpers private extension BloggingRemindersFlowSettingsViewController { diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift new file mode 100644 index 000000000000..9b943350c866 --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift @@ -0,0 +1,32 @@ +import UIKit +import WordPressUI + +final class BloggingRemindersNavigationController: UINavigationController { + private let onDismiss: (() -> Void)? + + required init(rootViewController: UIViewController, onDismiss: (() -> Void)? = nil) { + self.onDismiss = onDismiss + + super.init(rootViewController: rootViewController) + + setNavigationBarHidden(true, animated: false) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .systemBackground + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + if isBeingDismissedDirectlyOrByAncestor() { + onDismiss?() + } + } +} diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersPushPromptViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift similarity index 96% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersPushPromptViewController.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift index 5c694e8b4118..19d429f150b1 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersPushPromptViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift @@ -230,20 +230,6 @@ extension BloggingRemindersPushPromptViewController: BloggingRemindersActions { } } -// MARK: - DrawerPresentable - -extension BloggingRemindersPushPromptViewController: DrawerPresentable { - var collapsedHeight: DrawerHeight { - return .maxHeight - } -} - -extension BloggingRemindersPushPromptViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - return .expanded - } -} - // MARK: - Constants private enum TextContent { diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersTracker.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersTracker.swift similarity index 100% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/BloggingRemindersTracker.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersTracker.swift diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/CalendarDayToggleButton.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/CalendarDayToggleButton.swift similarity index 100% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/CalendarDayToggleButton.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/CalendarDayToggleButton.swift diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionButton.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionButton.swift similarity index 97% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionButton.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionButton.swift index 2dd59d12c661..ab64a5d8ef73 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionButton.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionButton.swift @@ -1,6 +1,6 @@ import UIKit -class TimeSelectionButton: UIButton { +final class BloggingRemindersTimeSelectionButton: UIButton { private(set) var selectedTime: String { didSet { diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionView.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift similarity index 91% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionView.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift index 973353ba2781..40aa9bd75d51 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionView.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift @@ -1,7 +1,7 @@ import UIKit /// A view that contains a time picker and a title reporting the selected time -class TimeSelectionView: UIView { +final class BloggingRemindersTimeSelectionView: UIView { private var selectedTime: Date @@ -19,8 +19,8 @@ class TimeSelectionView: UIView { titleBar.setSelectedTime(timePicker.date.toLocalTime()) } - private lazy var titleBar: TimeSelectionButton = { - let button = TimeSelectionButton(selectedTime: selectedTime.toLocalTime(), insets: Self.titleInsets) + private lazy var titleBar: BloggingRemindersTimeSelectionButton = { + let button = BloggingRemindersTimeSelectionButton(selectedTime: selectedTime.toLocalTime(), insets: Self.titleInsets) button.translatesAutoresizingMaskIntoConstraints = false button.isUserInteractionEnabled = false button.isChevronHidden = true diff --git a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift similarity index 65% rename from WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionViewController.swift rename to WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift index 16305668ca88..b9865ac7d24a 100644 --- a/WordPress/Classes/ViewRelated/Blog/Blogging Reminders/Time Selector/TimeSelectionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift @@ -1,7 +1,7 @@ import UIKit import WordPressUI -class TimeSelectionViewController: UIViewController { +final class BloggingRemindersTimeSelectionViewController: UIViewController { var preferredWidth: CGFloat? @@ -11,8 +11,8 @@ class TimeSelectionViewController: UIViewController { private var onDismiss: ((Date) -> Void)? - private lazy var timeSelectionView: TimeSelectionView = { - let view = TimeSelectionView(selectedTime: scheduledTime) + private lazy var timeSelectionView: BloggingRemindersTimeSelectionView = { + let view = BloggingRemindersTimeSelectionView(selectedTime: scheduledTime) view.translatesAutoresizingMaskIntoConstraints = false return view }() @@ -36,18 +36,6 @@ class TimeSelectionViewController: UIViewController { self.view = mainView } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - calculatePreferredSize() - } - - private func calculatePreferredSize() { - let targetSize = CGSize(width: view.bounds.width, - height: UIView.layoutFittingCompressedSize.height) - preferredContentSize = view.systemLayoutSizeFitting(targetSize) - navigationController?.preferredContentSize = preferredContentSize - } - override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) navigationController?.setNavigationBarHidden(false, animated: false) @@ -55,6 +43,7 @@ class TimeSelectionViewController: UIViewController { override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) + navigationController?.setNavigationBarHidden(true, animated: false) if isMovingFromParent { onDismiss?(timeSelectionView.getDate()) @@ -71,16 +60,3 @@ class TimeSelectionViewController: UIViewController { } } } - -// MARK: - DrawerPresentable -extension TimeSelectionViewController: DrawerPresentable { - var collapsedHeight: DrawerHeight { - return .intrinsicHeight - } -} - -extension TimeSelectionViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - return .collapsed - } -} diff --git a/WordPress/Classes/ViewRelated/Jetpack/Branding/Overlay/JetpackOverlayViewController.swift b/WordPress/Classes/ViewRelated/Jetpack/Branding/Overlay/JetpackOverlayViewController.swift index 3f17f95d9a15..ff9c853a6cc4 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Branding/Overlay/JetpackOverlayViewController.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Branding/Overlay/JetpackOverlayViewController.swift @@ -51,9 +51,3 @@ extension JetpackOverlayViewController: DrawerPresentable { .maxWidth } } - -extension JetpackOverlayViewController: ChildDrawerPositionable { - var preferredDrawerPosition: DrawerPosition { - .collapsed - } -} From 7fa8029bea36315d4d3656f890d4052542777685 Mon Sep 17 00:00:00 2001 From: kean Date: Mon, 30 Dec 2024 23:07:08 -0500 Subject: [PATCH 03/15] Simplify BloggingRemindersFlowIntroViewController --- .../BloggingRemindersFlow.swift | 2 +- ...gingRemindersFlowIntroViewController.swift | 32 ++++--------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift index 622047076dc7..3f1b3472c70e 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift @@ -40,7 +40,7 @@ final class BloggingRemindersFlow { if hasShownWeeklyRemindersFlow(for: blog) { showSettings() } else { - let introVC = BloggingRemindersFlowIntroViewController(for: blog, tracker: tracker, source: source) { [weak presentingViewController] in + let introVC = BloggingRemindersFlowIntroViewController(tracker: tracker) { [weak presentingViewController] in presentingViewController?.dismiss(animated: true) { showSettings() } diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift index 31447713322e..a9bb1eadee46 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift @@ -8,7 +8,7 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { private let stackView: UIStackView = { let stackView = UIStackView() stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.spacing = Metrics.stackSpacing + stackView.spacing = 20 stackView.axis = .vertical stackView.alignment = .center stackView.distribution = .equalSpacing @@ -52,18 +52,11 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { }) }() - private let blog: Blog private let tracker: BloggingRemindersTracker - private let source: BloggingRemindersTracker.FlowStartSource private let onNextTapped: () -> Void - init(for blog: Blog, - tracker: BloggingRemindersTracker, - source: BloggingRemindersTracker.FlowStartSource, - onNextTapped: @escaping () -> Void) { - self.blog = blog + init(tracker: BloggingRemindersTracker, onNextTapped: @escaping () -> Void) { self.tracker = tracker - self.source = source self.onNextTapped = onNextTapped super.init(nibName: nil, bundle: nil) @@ -105,23 +98,21 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { private func configureStackView() { view.addSubview(stackView) + let spacer = UIView() stackView.addArrangedSubviews([ imageView, titleLabel, promptLabel, + spacer, buttonNext ]) - stackView.setCustomSpacing(Metrics.afterPromptSpacing, after: promptLabel) + stackView.setCustomSpacing(8, after: titleLabel) + stackView.setCustomSpacing(24, after: promptLabel) } private func configureConstraints() { + stackView.pinEdges(to: view.safeAreaLayoutGuide, insets: UIEdgeInsets(.all, 24)) NSLayoutConstraint.activate([ - stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Metrics.edgeMargins.left), - stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Metrics.edgeMargins.right), - stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: Metrics.edgeMargins.top), - stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeBottomAnchor, constant: -Metrics.edgeMargins.bottom), - - buttonNext.heightAnchor.constraint(greaterThanOrEqualToConstant: Metrics.getStartedButtonHeight), buttonNext.widthAnchor.constraint(equalTo: stackView.widthAnchor), ]) } @@ -138,8 +129,6 @@ extension BloggingRemindersFlowIntroViewController: BloggingRemindersActions { } } -// MARK: - Constants - private enum Strings { static let introTitle = NSLocalizedString("bloggingRemindersPrompt.intro.title", value: "Blogging Reminders", comment: "Title of the Blogging Reminders Settings screen.") static let introDescription = NSLocalizedString("bloggingRemindersPrompt.intro.details", value: "Set up your blogging reminders on days you want to post.", comment: "Description on the first screen of the Blogging Reminders Settings flow called aftet post publishing.") @@ -149,10 +138,3 @@ private enum Strings { private enum Images { static let celebrationImageName = "reminders-celebration" } - -private enum Metrics { - static let edgeMargins = UIEdgeInsets(top: 46, left: 20, bottom: 20, right: 20) - static let stackSpacing: CGFloat = 20.0 - static let afterPromptSpacing: CGFloat = 24.0 - static let getStartedButtonHeight: CGFloat = 44.0 -} From baa1ae1baa8230a045a89349a773439ff624cec4 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 11:20:26 -0500 Subject: [PATCH 04/15] Add SpacerView --- .../WordPressUI/Views/SpacerView.swift | 54 +++++++++++++++++++ ...gingRemindersFlowIntroViewController.swift | 40 +++++--------- 2 files changed, 66 insertions(+), 28 deletions(-) create mode 100644 Modules/Sources/WordPressUI/Views/SpacerView.swift diff --git a/Modules/Sources/WordPressUI/Views/SpacerView.swift b/Modules/Sources/WordPressUI/Views/SpacerView.swift new file mode 100644 index 000000000000..2dd3e6bd46d6 --- /dev/null +++ b/Modules/Sources/WordPressUI/Views/SpacerView.swift @@ -0,0 +1,54 @@ +import UIKit + +public final class SpacerView: UIView { + public convenience init(minWidth: CGFloat) { + self.init() + + widthAnchor.constraint(greaterThanOrEqualToConstant: minWidth).isActive = true + } + + public convenience init(minHeight: CGFloat) { + self.init() + + heightAnchor.constraint(greaterThanOrEqualToConstant: minHeight).isActive = true + } + + public convenience init(width: CGFloat) { + self.init() + + widthAnchor.constraint(equalToConstant: width).isActive = true + } + + public convenience init(height: CGFloat) { + self.init() + + heightAnchor.constraint(equalToConstant: height).isActive = true + } + + public override init(frame: CGRect) { + super.init(frame: .zero) + + // Make sure it compresses or expands before any other views if needed. + setContentCompressionResistancePriority(.init(10), for: .horizontal) + setContentCompressionResistancePriority(.init(10), for: .vertical) + setContentHuggingPriority(.init(10), for: .horizontal) + setContentHuggingPriority(.init(10), for: .vertical) + } + + public override var intrinsicContentSize: CGSize { + CGSizeMake(0, 0) // Avoid ambiguous layout + } + + public required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } + + override public class var layerClass: AnyClass { + CATransformLayer.self // Draws nothing + } + + override public var backgroundColor: UIColor? { + get { return nil } + set { /* Do nothing */ } + } +} diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift index a9bb1eadee46..13666ba0dc1c 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift @@ -3,20 +3,8 @@ import WordPressUI final class BloggingRemindersFlowIntroViewController: UIViewController { - // MARK: - Subviews - - private let stackView: UIStackView = { - let stackView = UIStackView() - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.spacing = 20 - stackView.axis = .vertical - stackView.alignment = .center - stackView.distribution = .equalSpacing - return stackView - }() - private let imageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: Images.celebrationImageName)) + let imageView = UIImageView(image: UIImage(named: "reminders-celebration")) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.tintColor = .systemYellow return imageView @@ -73,8 +61,7 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { view.backgroundColor = .systemBackground - configureStackView() - configureConstraints() + setupView() promptLabel.text = Strings.introDescription } @@ -96,22 +83,23 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { // MARK: - View Configuration - private func configureStackView() { - view.addSubview(stackView) - let spacer = UIView() - stackView.addArrangedSubviews([ + private func setupView() { + let stackView = UIStackView(axis: .vertical, alignment: .center, spacing: 20, [ imageView, titleLabel, promptLabel, - spacer, + SpacerView(minHeight: 8), buttonNext ]) stackView.setCustomSpacing(8, after: titleLabel) stackView.setCustomSpacing(24, after: promptLabel) - } - private func configureConstraints() { - stackView.pinEdges(to: view.safeAreaLayoutGuide, insets: UIEdgeInsets(.all, 24)) + view.addSubview(stackView) + + var insets = UIEdgeInsets(.all, 24) + insets.top = 48 + + stackView.pinEdges(to: view.safeAreaLayoutGuide, insets: insets) NSLayoutConstraint.activate([ buttonNext.widthAnchor.constraint(equalTo: stackView.widthAnchor), ]) @@ -132,9 +120,5 @@ extension BloggingRemindersFlowIntroViewController: BloggingRemindersActions { private enum Strings { static let introTitle = NSLocalizedString("bloggingRemindersPrompt.intro.title", value: "Blogging Reminders", comment: "Title of the Blogging Reminders Settings screen.") static let introDescription = NSLocalizedString("bloggingRemindersPrompt.intro.details", value: "Set up your blogging reminders on days you want to post.", comment: "Description on the first screen of the Blogging Reminders Settings flow called aftet post publishing.") - static let introButtonTitle = NSLocalizedString("bloggingRemindersPrompt.intro.continueButton", value: "Set reminders", comment: "Title of the set goals button in the Blogging Reminders Settings flow.") -} - -private enum Images { - static let celebrationImageName = "reminders-celebration" + static let introButtonTitle = NSLocalizedString("bloggingRemindersPrompt.intro.continueButton", value: "Set Reminders", comment: "Title of the set goals button in the Blogging Reminders Settings flow.") } From 7e7716357fdb6035d68bb19972b7df2aae17a06b Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:17:46 -0500 Subject: [PATCH 05/15] Add BottomToolbarView --- .../Extensions/UIButton+Extensions.swift | 14 +++ .../WordPressUI/Views/BottomToolbarView.swift | 86 +++++++++++++++++++ .../WordPressUI/Views/SeparatorView.swift | 25 ++++++ .../ExperimentalFeaturesList.swift | 0 .../ExperimentalFeaturesViewModel.swift | 0 .../Feature.swift | 0 .../Extensions/UIButton+Extensions.swift | 13 --- .../Views}/RestApiUpgradePrompt.swift | 8 +- .../BloggingRemindersFlow.swift | 10 ++- ...gingRemindersFlowIntroViewController.swift | 66 ++++++++------ 10 files changed, 175 insertions(+), 47 deletions(-) create mode 100644 Modules/Sources/WordPressUI/Extensions/UIButton+Extensions.swift create mode 100644 Modules/Sources/WordPressUI/Views/BottomToolbarView.swift create mode 100644 Modules/Sources/WordPressUI/Views/SeparatorView.swift rename Modules/Sources/WordPressUI/Views/Settings/{Experimental Features => ExperimentalFeatures}/ExperimentalFeaturesList.swift (100%) rename Modules/Sources/WordPressUI/Views/Settings/{Experimental Features => ExperimentalFeatures}/ExperimentalFeaturesViewModel.swift (100%) rename Modules/Sources/WordPressUI/Views/Settings/{Experimental Features => ExperimentalFeatures}/Feature.swift (100%) rename {Modules/Sources/WordPressUI/Components => WordPress/Classes/ViewRelated/Blog/Blog Details/Views}/RestApiUpgradePrompt.swift (93%) diff --git a/Modules/Sources/WordPressUI/Extensions/UIButton+Extensions.swift b/Modules/Sources/WordPressUI/Extensions/UIButton+Extensions.swift new file mode 100644 index 000000000000..4c7b6581fb84 --- /dev/null +++ b/Modules/Sources/WordPressUI/Extensions/UIButton+Extensions.swift @@ -0,0 +1,14 @@ +import UIKit + +extension UIButton.Configuration { + public static func primary() -> UIButton.Configuration { + var configuration = UIButton.Configuration.borderedProminent() + configuration.titleTextAttributesTransformer = .init { attributes in + var attributes = attributes + attributes.font = UIFont.preferredFont(forTextStyle: .headline) + return attributes + } + configuration.buttonSize = .large + return configuration + } +} diff --git a/Modules/Sources/WordPressUI/Views/BottomToolbarView.swift b/Modules/Sources/WordPressUI/Views/BottomToolbarView.swift new file mode 100644 index 000000000000..14a7bb96c38e --- /dev/null +++ b/Modules/Sources/WordPressUI/Views/BottomToolbarView.swift @@ -0,0 +1,86 @@ +import UIKit +import Combine + +/// A custom bottom toolbar implementation that, unlike the native toolbar, +/// can accommodate larger buttons but shares a lot of its behavior including +/// edge appearance. +public class BottomToolbarView: UIView { + private let separator = SeparatorView.horizontal() + private let effectView = UIVisualEffectView() + private var isEdgeAppearanceEnabled = false + private weak var scrollView: UIScrollView? + private var cancellable: AnyCancellable? + + public let contentView = UIView() + + public override init(frame: CGRect) { + super.init(frame: frame) + + addSubview(effectView) + addSubview(separator) + + separator.pinEdges([.top, .horizontal]) + effectView.pinEdges() + + effectView.contentView.addSubview(contentView) + + contentView.pinEdges(to: effectView.contentView.safeAreaLayoutGuide, insets: UIEdgeInsets(.all, 20)) + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func layoutSubviews() { + super.layoutSubviews() + + updateScrollViewContentInsets() + } + + public override func safeAreaInsetsDidChange() { + super.safeAreaInsetsDidChange() + + updateScrollViewContentInsets() + } + + /// - warning: If you use this view, you'll typically need to take over the + /// scroll view content inset adjustment. + public func configure(in viewController: UIViewController, scrollView: UIScrollView) { + viewController.view.addSubview(self) + pinEdges([.horizontal, .bottom]) + self.scrollView = scrollView + + cancellable = scrollView.publisher(for: \.contentOffset, options: [.new]).sink { [weak self] offset in + self?.updateEdgeAppearance(animated: true) + } + updateScrollViewContentInsets() + updateEdgeAppearance(animated: false) + } + + private func updateEdgeAppearance(animated: Bool) { + guard let scrollView, let superview else { return } + + let isContentOverlapping = superview.convert(scrollView.contentLayoutGuide.layoutFrame, from: scrollView).maxY > (frame.minY + 16) + setEdgeAppearanceEnabled(!isContentOverlapping, animated: animated) + } + + private func setEdgeAppearanceEnabled(_ isEnabled: Bool, animated: Bool) { + guard isEdgeAppearanceEnabled != isEnabled else { return } + isEdgeAppearanceEnabled = isEnabled + + UIView.animate(withDuration: animated ? 0 : 0.33, delay: 0.0, options: [.allowUserInteraction, .beginFromCurrentState]) { + self.effectView.effect = isEnabled ? nil : UIBlurEffect(style: .extraLight) + self.separator.alpha = isEnabled ? 0 : 1 + } + } + + // The toolbar does no extend the safe area because it itself depends on it, + // so it resorts to changing `contentInset` instead. + private func updateScrollViewContentInsets() { + guard let scrollView else { return } + let bottomInset = bounds.height - safeAreaInsets.bottom + if scrollView.contentInset.bottom != bottomInset { + scrollView.contentInset.bottom = bottomInset + } + } +} diff --git a/Modules/Sources/WordPressUI/Views/SeparatorView.swift b/Modules/Sources/WordPressUI/Views/SeparatorView.swift new file mode 100644 index 000000000000..8d0d8b888ddb --- /dev/null +++ b/Modules/Sources/WordPressUI/Views/SeparatorView.swift @@ -0,0 +1,25 @@ +import UIKit + +public final class SeparatorView: UIView { + public static func horizontal() -> SeparatorView { + let view = SeparatorView() + view.heightAnchor.constraint(equalToConstant: 0.5).isActive = true + return view + } + + public static func vertical() -> SeparatorView { + let view = SeparatorView() + view.widthAnchor.constraint(equalToConstant: 0.5).isActive = true + return view + } + + public override init(frame: CGRect) { + super.init(frame: frame) + + backgroundColor = .separator + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Modules/Sources/WordPressUI/Views/Settings/Experimental Features/ExperimentalFeaturesList.swift b/Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/ExperimentalFeaturesList.swift similarity index 100% rename from Modules/Sources/WordPressUI/Views/Settings/Experimental Features/ExperimentalFeaturesList.swift rename to Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/ExperimentalFeaturesList.swift diff --git a/Modules/Sources/WordPressUI/Views/Settings/Experimental Features/ExperimentalFeaturesViewModel.swift b/Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/ExperimentalFeaturesViewModel.swift similarity index 100% rename from Modules/Sources/WordPressUI/Views/Settings/Experimental Features/ExperimentalFeaturesViewModel.swift rename to Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/ExperimentalFeaturesViewModel.swift diff --git a/Modules/Sources/WordPressUI/Views/Settings/Experimental Features/Feature.swift b/Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/Feature.swift similarity index 100% rename from Modules/Sources/WordPressUI/Views/Settings/Experimental Features/Feature.swift rename to Modules/Sources/WordPressUI/Views/Settings/ExperimentalFeatures/Feature.swift diff --git a/WordPress/Classes/Extensions/UIButton+Extensions.swift b/WordPress/Classes/Extensions/UIButton+Extensions.swift index 2194627639e6..68b46e1ee49e 100644 --- a/WordPress/Classes/Extensions/UIButton+Extensions.swift +++ b/WordPress/Classes/Extensions/UIButton+Extensions.swift @@ -31,16 +31,3 @@ extension UIButton { }()) } } - -extension UIButton.Configuration { - static func primary() -> UIButton.Configuration { - var configuration = UIButton.Configuration.borderedProminent() - configuration.titleTextAttributesTransformer = .init { attributes in - var attributes = attributes - attributes.font = UIFont.preferredFont(forTextStyle: .headline) - return attributes - } - configuration.buttonSize = .large - return configuration - } -} diff --git a/Modules/Sources/WordPressUI/Components/RestApiUpgradePrompt.swift b/WordPress/Classes/ViewRelated/Blog/Blog Details/Views/RestApiUpgradePrompt.swift similarity index 93% rename from Modules/Sources/WordPressUI/Components/RestApiUpgradePrompt.swift rename to WordPress/Classes/ViewRelated/Blog/Blog Details/Views/RestApiUpgradePrompt.swift index 7b6160afff0c..a276f9a5fd18 100644 --- a/Modules/Sources/WordPressUI/Components/RestApiUpgradePrompt.swift +++ b/WordPress/Classes/ViewRelated/Blog/Blog Details/Views/RestApiUpgradePrompt.swift @@ -1,3 +1,5 @@ +import UIKit +import WordPressUI import SwiftUI public struct RestApiUpgradePrompt: View { @@ -40,9 +42,3 @@ public struct RestApiUpgradePrompt: View { } } } - -#Preview { - RestApiUpgradePrompt(localizedFeatureName: "User Management") { - debugPrint("Tapped Get Started") - } -} diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift index 3f1b3472c70e..18aa466c0054 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift @@ -45,8 +45,14 @@ final class BloggingRemindersFlow { showSettings() } } - introVC.sheetPresentationController?.detents = [.medium()] - presentingViewController.present(introVC, animated: true) + let navigationVC = UINavigationController(rootViewController: introVC) + if presentingViewController.traitCollection.horizontalSizeClass == .regular { + navigationVC.preferredContentSize = CGSize(width: 375, height: 420) + } else { + navigationVC.sheetPresentationController?.detents = [.medium()] + navigationVC.sheetPresentationController?.preferredCornerRadius = 16 + } + presentingViewController.present(navigationVC, animated: true) } setHasShownWeeklyRemindersFlow(for: blog) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift index 13666ba0dc1c..8d62ab6b8cd4 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowIntroViewController.swift @@ -1,11 +1,11 @@ import UIKit -import WordPressUI + import WordPressUI final class BloggingRemindersFlowIntroViewController: UIViewController { + private let scrollView = UIScrollView() private let imageView: UIImageView = { let imageView = UIImageView(image: UIImage(named: "reminders-celebration")) - imageView.translatesAutoresizingMaskIntoConstraints = false imageView.tintColor = .systemYellow return imageView }() @@ -13,8 +13,7 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { private let titleLabel: UILabel = { let label = UILabel() label.adjustsFontForContentSizeCategory = true - label.adjustsFontSizeToFitWidth = true - label.font = WPStyleGuide.serifFontForTextStyle(.title1, fontWeight: .semibold) + label.font = .preferredFont(forTextStyle: .title1).withWeight(.semibold) label.numberOfLines = 2 label.textAlignment = .center label.text = Strings.introTitle @@ -24,7 +23,6 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { private let promptLabel: UILabel = { let label = UILabel() label.adjustsFontForContentSizeCategory = true - label.adjustsFontSizeToFitWidth = true label.font = .preferredFont(forTextStyle: .body) label.numberOfLines = 5 label.textAlignment = .center @@ -35,12 +33,17 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { var configuration = UIButton.Configuration.primary() configuration.title = Strings.introButtonTitle - return UIButton(configuration: configuration, primaryAction: .init { [weak self] _ in - self?.buttonGetStartedTapped() + let button = UIButton(configuration: configuration, primaryAction: .init { [weak self] _ in + self?.buttonContinueTapped() }) + button.titleLabel?.adjustsFontForContentSizeCategory = true + return button }() + private let bottomBarView = BottomToolbarView() + private let tracker: BloggingRemindersTracker + private var isOnNextTapped = false private let onNextTapped: () -> Void init(tracker: BloggingRemindersTracker, onNextTapped: @escaping () -> Void) { @@ -62,7 +65,13 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { view.backgroundColor = .systemBackground setupView() + setupBottomBar() + promptLabel.text = Strings.introDescription + + navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: .init(handler: { [weak self] _ in + self?.buttonCloseTapped() + })) } override func viewDidAppear(_ animated: Bool) { @@ -74,9 +83,7 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) - // If a parent VC is being dismissed, and this is the last view shown in its navigation controller, we'll assume - // the flow was interrupted. - if isBeingDismissedDirectlyOrByAncestor() && navigationController?.viewControllers.last == self { + if !isOnNextTapped { tracker.flowDismissed(source: .main) } } @@ -87,33 +94,40 @@ final class BloggingRemindersFlowIntroViewController: UIViewController { let stackView = UIStackView(axis: .vertical, alignment: .center, spacing: 20, [ imageView, titleLabel, - promptLabel, - SpacerView(minHeight: 8), - buttonNext + promptLabel ]) stackView.setCustomSpacing(8, after: titleLabel) - stackView.setCustomSpacing(24, after: promptLabel) - view.addSubview(stackView) + scrollView.showsVerticalScrollIndicator = false + scrollView.alwaysBounceVertical = false - var insets = UIEdgeInsets(.all, 24) - insets.top = 48 + scrollView.addSubview(stackView) + view.addSubview(scrollView) - stackView.pinEdges(to: view.safeAreaLayoutGuide, insets: insets) - NSLayoutConstraint.activate([ - buttonNext.widthAnchor.constraint(equalTo: stackView.widthAnchor), - ]) + stackView.pinEdges(insets: UIEdgeInsets(.all, 20)) + stackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true + + scrollView.pinEdges() } - private func buttonGetStartedTapped() { + private func setupBottomBar() { + bottomBarView.contentView.addSubview(buttonNext) + buttonNext.pinEdges() + + bottomBarView.configure(in: self, scrollView: scrollView) + } + + // MARK: Actions + + private func buttonContinueTapped() { tracker.buttonPressed(button: .continue, screen: .main) + isOnNextTapped = true onNextTapped() } -} -extension BloggingRemindersFlowIntroViewController: BloggingRemindersActions { - @objc private func dismissTapped() { - dismiss(from: .dismiss, screen: .main, tracker: tracker) + private func buttonCloseTapped() { + tracker.buttonPressed(button: .dismiss, screen: .main) + presentingViewController?.dismiss(animated: true, completion: nil) } } From 57375a63acaf9310b4be6ad882212ac51a7b77dc Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:33:55 -0500 Subject: [PATCH 06/15] Fix notice covering the blogging reminders fow --- .../Blog/BloggingReminders/BloggingRemindersFlow.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift index 18aa466c0054..361b0d81fb55 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlow.swift @@ -1,4 +1,5 @@ import UIKit +import WordPressFlux import WordPressUI final class BloggingRemindersFlow { @@ -27,10 +28,8 @@ final class BloggingRemindersFlow { do { let settingsVC = try BloggingRemindersFlowSettingsViewController(for: blog, tracker: tracker, delegate: delegate) let navigationController = BloggingRemindersNavigationController(rootViewController: settingsVC, onDismiss: { - NoticesDispatch.unlock() onDismiss?() }) - NoticesDispatch.lock() presentingViewController?.present(navigationController, animated: true) } catch { wpAssertionFailure("Could not instantiate the blogging reminders settings VC", userInfo: ["error": "\(error)"]) @@ -56,6 +55,7 @@ final class BloggingRemindersFlow { } setHasShownWeeklyRemindersFlow(for: blog) + ActionDispatcher.dispatch(NoticeAction.dismiss) } // MARK: - Weekly reminders flow presentation status From eb5f4e332075acf2ff20e61c61a02c7812453bbd Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:37:22 -0500 Subject: [PATCH 07/15] Replace FancyButton --- .../BloggingRemindersFlowSettingsViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift index 22f605d939b9..e374c584e285 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift @@ -54,8 +54,8 @@ final class BloggingRemindersFlowSettingsViewController: UIViewController { }() private lazy var button: UIButton = { - let button = FancyButton() - button.isPrimary = true + var configuration = UIButton.Configuration.primary() + let button = UIButton(configuration: configuration, primaryAction: nil) button.addTarget(self, action: #selector(notifyMeButtonTapped), for: .touchUpInside) return button }() From c3e4ed842806d63934fab02cf2f18db1e6994437 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:41:26 -0500 Subject: [PATCH 08/15] Add close button to BloggingRemindersFlowSettingsViewController --- ...emindersFlowCompletionViewController.swift | 2 -- ...gRemindersFlowSettingsViewController.swift | 21 +++++++------------ ...loggingRemindersNavigationController.swift | 2 -- ...ingRemindersPushPromptViewController.swift | 2 -- ...RemindersTimeSelectionViewController.swift | 2 -- 5 files changed, 7 insertions(+), 22 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift index c71158b053ff..df0176ce46c6 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift @@ -100,8 +100,6 @@ class BloggingRemindersFlowCompletionViewController: UIViewController { configureConstraints() configurePromptLabel() configureTitleLabel() - - navigationController?.setNavigationBarHidden(true, animated: false) } override func viewDidAppear(_ animated: Bool) { diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift index e374c584e285..d052ea4bdf36 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift @@ -279,13 +279,16 @@ final class BloggingRemindersFlowSettingsViewController: UIViewController { refreshFrequencyLabel() showFullUI(shouldShowFullUI) + + navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .close, primaryAction: .init(handler: { [weak self] _ in + self?.presentingViewController?.dismiss(animated: true) + })) } override func viewDidAppear(_ animated: Bool) { - tracker.screenShown(.dayPicker) - super.viewDidAppear(animated) - calculatePreferredContentSize() + + tracker.screenShown(.dayPicker) } override func viewDidDisappear(_ animated: Bool) { @@ -298,11 +301,6 @@ final class BloggingRemindersFlowSettingsViewController: UIViewController { } } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - calculatePreferredContentSize() - } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) @@ -311,8 +309,8 @@ final class BloggingRemindersFlowSettingsViewController: UIViewController { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) + showFullUI(shouldShowFullUI) - calculatePreferredContentSize() } // MARK: - Actions @@ -498,11 +496,6 @@ private extension BloggingRemindersFlowSettingsViewController { frequencyLabel.sizeToFit() } - func calculatePreferredContentSize() { - let size = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height) - preferredContentSize = view.systemLayoutSizeFitting(size) - } - func configureStackView() { view.addSubview(stackView) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift index 9b943350c866..ae119f8e8ad3 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersNavigationController.swift @@ -8,8 +8,6 @@ final class BloggingRemindersNavigationController: UINavigationController { self.onDismiss = onDismiss super.init(rootViewController: rootViewController) - - setNavigationBarHidden(true, animated: false) } required init?(coder aDecoder: NSCoder) { diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift index 19d429f150b1..27c5a739f310 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift @@ -124,8 +124,6 @@ class BloggingRemindersPushPromptViewController: UIViewController { view.addSubview(turnOnNotificationsButton) configureConstraints() - - navigationController?.setNavigationBarHidden(true, animated: false) } override func viewDidAppear(_ animated: Bool) { diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift index b9865ac7d24a..c8af9acd0fca 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift @@ -38,13 +38,11 @@ final class BloggingRemindersTimeSelectionViewController: UIViewController { override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - navigationController?.setNavigationBarHidden(false, animated: false) } override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - navigationController?.setNavigationBarHidden(true, animated: false) if isMovingFromParent { onDismiss?(timeSelectionView.getDate()) } From cc29674be03dd57aeb8df707d72a07ae0e7ed288 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:48:28 -0500 Subject: [PATCH 09/15] Fix BloggingRemindersTimeSelectionViewController presentation --- ...gRemindersFlowSettingsViewController.swift | 1 - .../BloggingRemindersTimeSelectionView.swift | 5 ++-- ...RemindersTimeSelectionViewController.swift | 24 ++++++------------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift index d052ea4bdf36..99f93f2931e4 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowSettingsViewController.swift @@ -412,7 +412,6 @@ private extension BloggingRemindersFlowSettingsViewController { self?.refreshNextButton() self?.refreshFrequencyLabel() } - viewController.preferredWidth = self.view.frame.width navigationController?.pushViewController(viewController, animated: true) } diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift index 40aa9bd75d51..0160e57fc9c7 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionView.swift @@ -1,4 +1,5 @@ import UIKit +import WordPressUI /// A view that contains a time picker and a title reporting the selected time final class BloggingRemindersTimeSelectionView: UIView { @@ -65,9 +66,9 @@ final class BloggingRemindersTimeSelectionView: UIView { self.selectedTime = selectedTime super.init(frame: .zero) - backgroundColor = .systemBackground addSubview(verticalStackView) - pinSubviewToSafeArea(verticalStackView) + verticalStackView.pinEdges(to: safeAreaLayoutGuide) + NSLayoutConstraint.activate([ timePicker.centerXAnchor.constraint(equalTo: centerXAnchor), titleBar.widthAnchor.constraint(equalTo: widthAnchor), diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift index c8af9acd0fca..99b75e03bda1 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/TimeSelector/BloggingRemindersTimeSelectionViewController.swift @@ -2,20 +2,13 @@ import UIKit import WordPressUI final class BloggingRemindersTimeSelectionViewController: UIViewController { - - var preferredWidth: CGFloat? - private let scheduledTime: Date private let tracker: BloggingRemindersTracker private var onDismiss: ((Date) -> Void)? - private lazy var timeSelectionView: BloggingRemindersTimeSelectionView = { - let view = BloggingRemindersTimeSelectionView(selectedTime: scheduledTime) - view.translatesAutoresizingMaskIntoConstraints = false - return view - }() + private lazy var timeSelectionView = BloggingRemindersTimeSelectionView(selectedTime: scheduledTime) init(scheduledTime: Date, tracker: BloggingRemindersTracker, onDismiss: ((Date) -> Void)? = nil) { self.scheduledTime = scheduledTime @@ -28,16 +21,13 @@ final class BloggingRemindersTimeSelectionViewController: UIViewController { fatalError("init(coder:) has not been implemented") } - override func loadView() { - let mainView = timeSelectionView - if let width = preferredWidth { - mainView.widthAnchor.constraint(equalToConstant: width).isActive = true - } - self.view = mainView - } + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = .systemBackground - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) + view.addSubview(timeSelectionView) + timeSelectionView.pinEdges([.top, .horizontal]) } override func viewWillDisappear(_ animated: Bool) { From 9605dcc2c291a8bd4513be11784746f3ed1d4671 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:52:48 -0500 Subject: [PATCH 10/15] Remove FancyButton from BloggingRemindersPushPromptViewController --- .../BloggingRemindersPushPromptViewController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift index 27c5a739f310..1462d66e1072 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift @@ -1,7 +1,7 @@ import UIKit import WordPressUI -class BloggingRemindersPushPromptViewController: UIViewController { +final class BloggingRemindersPushPromptViewController: UIViewController { // MARK: - Subviews @@ -58,12 +58,12 @@ class BloggingRemindersPushPromptViewController: UIViewController { }() private lazy var turnOnNotificationsButton: UIButton = { - let button = FancyButton() + var configuration = UIButton.Configuration.primary() + configuration.title = TextContent.turnOnButtonTitle + + let button = UIButton(configuration: configuration, primaryAction: nil) button.translatesAutoresizingMaskIntoConstraints = false - button.isPrimary = true - button.setTitle(TextContent.turnOnButtonTitle, for: .normal) button.addTarget(self, action: #selector(turnOnButtonTapped), for: .touchUpInside) - button.titleLabel?.adjustsFontSizeToFitWidth = true return button }() From 145a0991a74e0c924fe17c6e966045db5b364b06 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:53:32 -0500 Subject: [PATCH 11/15] Remove dismiss button (it now shows back) --- ...BloggingRemindersPushPromptViewController.swift | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift index 1462d66e1072..a035ddcb23db 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift @@ -67,15 +67,6 @@ final class BloggingRemindersPushPromptViewController: UIViewController { return button }() - private lazy var dismissButton: UIButton = { - let button = UIButton(type: .custom) - button.translatesAutoresizingMaskIntoConstraints = false - button.setImage(.gridicon(.cross), for: .normal) - button.tintColor = .secondaryLabel - button.addTarget(self, action: #selector(dismissTapped), for: .touchUpInside) - return button - }() - // MARK: - Properties /// Indicates whether push notifications have been disabled or not. @@ -118,7 +109,6 @@ final class BloggingRemindersPushPromptViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground - view.addSubview(dismissButton) configureStackView() @@ -188,9 +178,6 @@ final class BloggingRemindersPushPromptViewController: UIViewController { turnOnNotificationsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Metrics.edgeMargins.left), turnOnNotificationsButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Metrics.edgeMargins.right), turnOnNotificationsButton.bottomAnchor.constraint(equalTo: view.safeBottomAnchor, constant: -Metrics.edgeMargins.bottom), - - dismissButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Metrics.dismissButtonMargin), - dismissButton.topAnchor.constraint(equalTo: view.topAnchor, constant: Metrics.dismissButtonMargin) ]) } @@ -247,7 +234,6 @@ private enum Images { } private enum Metrics { - static let dismissButtonMargin: CGFloat = 20.0 static let edgeMargins = UIEdgeInsets(top: 80, left: 28, bottom: 80, right: 28) static let stackSpacing: CGFloat = 20.0 static let turnOnButtonHeight: CGFloat = 44.0 From ac5382bf3f510f59f6ca34074667a1c91d209267 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 14:57:05 -0500 Subject: [PATCH 12/15] Update BloggingRemindersPushPromptViewController layout --- ...oggingRemindersPushPromptViewController.swift | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift index a035ddcb23db..51e05e817800 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersPushPromptViewController.swift @@ -133,22 +133,12 @@ final class BloggingRemindersPushPromptViewController: UIViewController { } - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - calculatePreferredContentSize() - } - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) hintLabel.isHidden = traitCollection.preferredContentSizeCategory.isAccessibilityCategory } - private func calculatePreferredContentSize() { - let size = CGSize(width: view.bounds.width, height: UIView.layoutFittingCompressedSize.height) - preferredContentSize = view.systemLayoutSizeFitting(size) - } - @objc private func applicationBecameActive() { refreshPushAuthorizationStatus() @@ -174,10 +164,9 @@ final class BloggingRemindersPushPromptViewController: UIViewController { stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: Metrics.edgeMargins.top), turnOnNotificationsButton.topAnchor.constraint(greaterThanOrEqualTo: stackView.bottomAnchor, constant: Metrics.edgeMargins.bottom), - turnOnNotificationsButton.heightAnchor.constraint(greaterThanOrEqualToConstant: Metrics.turnOnButtonHeight), turnOnNotificationsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Metrics.edgeMargins.left), turnOnNotificationsButton.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Metrics.edgeMargins.right), - turnOnNotificationsButton.bottomAnchor.constraint(equalTo: view.safeBottomAnchor, constant: -Metrics.edgeMargins.bottom), + turnOnNotificationsButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -Metrics.edgeMargins.bottom), ]) } @@ -234,7 +223,6 @@ private enum Images { } private enum Metrics { - static let edgeMargins = UIEdgeInsets(top: 80, left: 28, bottom: 80, right: 28) + static let edgeMargins = UIEdgeInsets(top: 80, left: 20, bottom: 20, right: 20) static let stackSpacing: CGFloat = 20.0 - static let turnOnButtonHeight: CGFloat = 44.0 } From 6aafa193a3532bb9a7857d1bef8f349586b20b38 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 15:04:54 -0500 Subject: [PATCH 13/15] Remove FancyButton from BloggingRemindersFlowCompletionViewController --- .../BloggingRemindersFlowCompletionViewController.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift index df0176ce46c6..f528a9f93e43 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift @@ -1,7 +1,7 @@ import UIKit import WordPressUI -class BloggingRemindersFlowCompletionViewController: UIViewController { +final class BloggingRemindersFlowCompletionViewController: UIViewController { // MARK: - Subviews @@ -57,8 +57,10 @@ class BloggingRemindersFlowCompletionViewController: UIViewController { }() private lazy var doneButton: UIButton = { - let button = FancyButton() - button.isPrimary = true + var configuration = UIButton.Configuration.primary() + configuration.title = TextContent.doneButtonTitle + + let button = UIButton(configuration: configuration, primaryAction: nil) button.setTitle(TextContent.doneButtonTitle, for: .normal) button.addTarget(self, action: #selector(doneButtonTapped), for: .touchUpInside) return button From d8c821b2a0bd6a255ef37adf0ee8f60c8beca384 Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 15:12:35 -0500 Subject: [PATCH 14/15] Update BloggingRemindersFlowCompletionViewController layout --- ...emindersFlowCompletionViewController.swift | 82 ++++++++----------- 1 file changed, 34 insertions(+), 48 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift index f528a9f93e43..86d16817cfb4 100644 --- a/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift +++ b/WordPress/Classes/ViewRelated/Blog/BloggingReminders/BloggingRemindersFlowCompletionViewController.swift @@ -5,18 +5,10 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { // MARK: - Subviews - private let stackView: UIStackView = { - let stackView = UIStackView() - stackView.translatesAutoresizingMaskIntoConstraints = false - stackView.spacing = Metrics.stackSpacing - stackView.axis = .vertical - stackView.alignment = .center - stackView.distribution = .equalSpacing - return stackView - }() + private let scrollView = UIScrollView() private let imageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: Images.bellImageName)) + let imageView = UIImageView(image: UIImage(named: "reminders-bell")) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.tintColor = .systemYellow return imageView @@ -25,7 +17,6 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { private let titleLabel: UILabel = { let label = UILabel() label.adjustsFontForContentSizeCategory = true - label.adjustsFontSizeToFitWidth = true label.font = WPStyleGuide.serifFontForTextStyle(.title1, fontWeight: .semibold) label.numberOfLines = 2 label.textAlignment = .center @@ -36,7 +27,6 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { private let promptLabel: UILabel = { let label = UILabel() label.adjustsFontForContentSizeCategory = true - label.adjustsFontSizeToFitWidth = true label.font = .preferredFont(forTextStyle: .body) label.numberOfLines = 6 label.textAlignment = .center @@ -47,7 +37,6 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { private let hintLabel: UILabel = { let label = UILabel() label.adjustsFontForContentSizeCategory = true - label.adjustsFontSizeToFitWidth = true label.font = .preferredFont(forTextStyle: .footnote) label.text = TextContent.completionUpdateHint label.numberOfLines = 3 @@ -66,6 +55,8 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { return button }() + private let bottomBarView = BottomToolbarView() + // MARK: - Initializers let blog: Blog @@ -96,18 +87,22 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() + view.backgroundColor = .systemBackground - configureStackView() - configureConstraints() + setupView() + setupBottomBar() + configurePromptLabel() configureTitleLabel() + + navigationController?.setNavigationBarHidden(true, animated: false) } override func viewDidAppear(_ animated: Bool) { - tracker.screenShown(.allSet) - super.viewDidAppear(animated) + + tracker.screenShown(.allSet) } override func viewDidDisappear(_ animated: Bool) { @@ -118,40 +113,39 @@ final class BloggingRemindersFlowCompletionViewController: UIViewController { if isBeingDismissedDirectlyOrByAncestor() && navigationController?.viewControllers.last == self { tracker.flowCompleted() } - - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - hintLabel.isHidden = traitCollection.preferredContentSizeCategory.isAccessibilityCategory } // MARK: - View Configuration - private func configureStackView() { - view.addSubview(stackView) - - stackView.addArrangedSubviews([ + private func setupView() { + let stackView = UIStackView(axis: .vertical, alignment: .center, spacing: 8, [ imageView, titleLabel, promptLabel, - hintLabel, - doneButton + hintLabel ]) - stackView.setCustomSpacing(Metrics.afterHintSpacing, after: hintLabel) + stackView.setCustomSpacing(16, after: titleLabel) + + scrollView.showsVerticalScrollIndicator = false + scrollView.alwaysBounceVertical = false + + scrollView.addSubview(stackView) + view.addSubview(scrollView) + + var insets = UIEdgeInsets(.all, 20) + insets.top = 48 + + stackView.pinEdges(insets: insets) + stackView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true + + scrollView.pinEdges() } - private func configureConstraints() { - NSLayoutConstraint.activate([ - stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Metrics.edgeMargins.left), - stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -Metrics.edgeMargins.right), - stackView.topAnchor.constraint(equalTo: view.topAnchor, constant: Metrics.edgeMargins.top), - stackView.bottomAnchor.constraint(lessThanOrEqualTo: view.safeBottomAnchor, constant: -Metrics.edgeMargins.bottom), + private func setupBottomBar() { + bottomBarView.contentView.addSubview(doneButton) + doneButton.pinEdges() - doneButton.heightAnchor.constraint(greaterThanOrEqualToConstant: Metrics.doneButtonHeight), - doneButton.widthAnchor.constraint(equalTo: stackView.widthAnchor), - ]) + bottomBarView.configure(in: self, scrollView: scrollView) } // Populates the prompt label with formatted text detailing the reminders set by the user. @@ -226,14 +220,6 @@ private enum TextContent { static let doneButtonTitle = NSLocalizedString("Done", comment: "Title for a Done button.") } -private enum Images { - static let bellImageName = "reminders-bell" -} - private enum Metrics { - static let edgeMargins = UIEdgeInsets(top: 46, left: 20, bottom: 20, right: 20) - static let stackSpacing: CGFloat = 20.0 - static let doneButtonHeight: CGFloat = 44.0 - static let afterHintSpacing: CGFloat = 24.0 static let promptTextLineSpacing: CGFloat = 1.5 } From 84ac565fa2e353089ac470bf50fa896ca935dcad Mon Sep 17 00:00:00 2001 From: kean Date: Tue, 31 Dec 2024 15:20:16 -0500 Subject: [PATCH 15/15] Update releaes notes --- RELEASE-NOTES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 14842c841edb..e66b9081a057 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -3,6 +3,7 @@ * [**] Add new lightbox screen for images with modern transitions and enhanced performance [#23922] * [*] Add prefetching to Reader streams [#23928] * [*] Fix an issue with blogging reminders prompt not being shown after publishing a new post [#23930] +* [*] Fix transitions in Blogging Reminders flow, improve accessibiliy, add close buttons [#23931] 25.6 -----