diff --git a/Mastodon/Scene/Onboarding/Welcome/View/Pages/WelcomeContentViewController.swift b/Mastodon/Scene/Onboarding/Welcome/View/Pages/WelcomeContentViewController.swift index 7bd20d033..a6910a281 100644 --- a/Mastodon/Scene/Onboarding/Welcome/View/Pages/WelcomeContentViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/View/Pages/WelcomeContentViewController.swift @@ -8,21 +8,21 @@ import UIKit class WelcomeContentViewController: UIViewController { - - let page: WelcomeContentPage - var contentView: WelcomeContentPageView { - view as! WelcomeContentPageView - } - - init(page: WelcomeContentPage) { - self.page = page - super.init(nibName: nil, bundle: nil) - } - - override func loadView() { - let pageView = WelcomeContentPageView(page: page) - self.view = pageView - } - - required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + let page: WelcomeContentPage + var contentView: WelcomeContentPageView { + view as! WelcomeContentPageView + } + + init(page: WelcomeContentPage) { + self.page = page + super.init(nibName: nil, bundle: nil) + } + + override func loadView() { + let pageView = WelcomeContentPageView(page: page) + self.view = pageView + } + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index 2af9fb629..12324ec9c 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -12,222 +12,230 @@ import MastodonCore import MastodonLocalization final class WelcomeViewController: UIViewController, NeedsDependency { - - weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } - weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } - - var disposeBag = Set() - var observations = Set() - private(set) lazy var viewModel = WelcomeViewModel(context: context) - - let welcomeIllustrationView = WelcomeIllustrationView() - - private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:))) - - let buttonContainer = UIStackView() - - private(set) lazy var signUpButton: PrimaryActionButton = { - let button = PrimaryActionButton() - button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false - button.contentEdgeInsets = WelcomeViewController.actionButtonPadding - button.titleLabel?.adjustsFontForContentSizeCategory = true - button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) - button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal) - let backgroundImageColor: UIColor = .white - let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0) - button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) - button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) - button.setTitleColor(.black, for: .normal) - return button - }() - let signUpButtonShadowView = UIView() - - private(set) lazy var signInButton: UIButton = { - let button = UIButton() - button.contentEdgeInsets = WelcomeViewController.actionButtonPadding - button.titleLabel?.adjustsFontForContentSizeCategory = true - button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) - button.setTitle(L10n.Scene.Welcome.logIn, for: .normal) - let titleColor: UIColor = UIColor.white.withAlphaComponent(0.9) - button.setTitleColor(titleColor, for: .normal) - button.setTitleColor(titleColor.withAlphaComponent(0.3), for: .highlighted) - return button - }() - - private(set) lazy var pageViewController: UIPageViewController = { - let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) - pageController.setViewControllers([WelcomeContentViewController(page: .whatIsMastodon)], direction: .forward, animated: false) - return pageController - }() - var currentPage: WelcomeContentPage = .whatIsMastodon - var currentPageOffset = 0 -} - -extension WelcomeViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - definesPresentationContext = true - preferredContentSize = CGSize(width: 547, height: 678) - - navigationController?.navigationBar.prefersLargeTitles = true - view.overrideUserInterfaceStyle = .light - - setupOnboardingAppearance() - - view.addSubview(welcomeIllustrationView) - welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false - - NSLayoutConstraint.activate([ - welcomeIllustrationView.topAnchor.constraint(equalTo: view.topAnchor), - welcomeIllustrationView.leadingAnchor.constraint(equalTo: view.leadingAnchor), - view.trailingAnchor.constraint(equalTo: welcomeIllustrationView.trailingAnchor), - view.bottomAnchor.constraint(equalTo: welcomeIllustrationView.bottomAnchor) - ]) - - buttonContainer.axis = .vertical - buttonContainer.spacing = 12 - buttonContainer.isLayoutMarginsRelativeArrangement = true - - buttonContainer.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(buttonContainer) - NSLayoutConstraint.activate([ - buttonContainer.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), - buttonContainer.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), - view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor), - ]) - - signUpButton.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addArrangedSubview(signUpButton) - NSLayoutConstraint.activate([ - signUpButton.heightAnchor.constraint(greaterThanOrEqualToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), - ]) - signInButton.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addArrangedSubview(signInButton) - NSLayoutConstraint.activate([ - signInButton.heightAnchor.constraint(greaterThanOrEqualToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), - ]) - - signUpButtonShadowView.translatesAutoresizingMaskIntoConstraints = false - buttonContainer.addSubview(signUpButtonShadowView) - buttonContainer.sendSubviewToBack(signUpButtonShadowView) - signUpButtonShadowView.pinTo(to: signUpButton) - - signUpButton.addTarget(self, action: #selector(signUpButtonDidClicked(_:)), for: .touchUpInside) - signInButton.addTarget(self, action: #selector(signInButtonDidClicked(_:)), for: .touchUpInside) - - pageViewController.delegate = self - pageViewController.dataSource = self - addChild(pageViewController) - pageViewController.view.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(pageViewController.view) - pageViewController.didMove(toParent: self) - - let scrollviews = pageViewController.view.subviews.filter { type(of: $0).isSubclass(of: UIScrollView.self) }.compactMap { $0 as? UIScrollView } - - for scrollView in scrollviews { - scrollView.delegate = self - } - - NSLayoutConstraint.activate([ - pageViewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - pageViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), - view.trailingAnchor.constraint(equalTo: pageViewController.view.trailingAnchor), - buttonContainer.topAnchor.constraint(equalTo: pageViewController.view.bottomAnchor, constant: 16), - ]) - - viewModel.$needsShowDismissEntry - .receive(on: DispatchQueue.main) - .sink { [weak self] needsShowDismissEntry in - guard let self = self else { return } - self.navigationItem.leftBarButtonItem = needsShowDismissEntry ? self.dismissBarButtonItem : nil - } - .store(in: &disposeBag) - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - setupButtonShadowView() - } - - override func viewSafeAreaInsetsDidChange() { - super.viewSafeAreaInsetsDidChange() - - var overlap: CGFloat = 5 - // shift illustration down for non-notch phone - if view.safeAreaInsets.bottom == 0 { - overlap += 56 + private enum Constants { + static let topAnchorInset: CGFloat = 20 } - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - super.traitCollectionDidChange(previousTraitCollection) - - view.layoutIfNeeded() - - setupIllustrationLayout() - setupButtonShadowView() - } + + weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } + weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } } + + var disposeBag = Set() + var observations = Set() + private(set) lazy var viewModel = WelcomeViewModel(context: context) + + let welcomeIllustrationView = WelcomeIllustrationView() + + private(set) lazy var dismissBarButtonItem = UIBarButtonItem(barButtonSystemItem: .close, target: self, action: #selector(WelcomeViewController.dismissBarButtonItemDidPressed(_:))) + + let buttonContainer = UIStackView() + + private(set) lazy var signUpButton: PrimaryActionButton = { + let button = PrimaryActionButton() + button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false + button.contentEdgeInsets = WelcomeViewController.actionButtonPadding + button.titleLabel?.adjustsFontForContentSizeCategory = true + button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) + button.setTitle(L10n.Common.Controls.Actions.signUp, for: .normal) + let backgroundImageColor: UIColor = .white + let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0) + button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) + button.setBackgroundImage(.placeholder(color: backgroundImageHighlightedColor), for: .highlighted) + button.setTitleColor(.black, for: .normal) + return button + }() + let signUpButtonShadowView = UIView() + + private(set) lazy var signInButton: UIButton = { + let button = UIButton() + button.contentEdgeInsets = WelcomeViewController.actionButtonPadding + button.titleLabel?.adjustsFontForContentSizeCategory = true + button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold)) + button.setTitle(L10n.Scene.Welcome.logIn, for: .normal) + let titleColor: UIColor = UIColor.white.withAlphaComponent(0.9) + button.setTitleColor(titleColor, for: .normal) + button.setTitleColor(titleColor.withAlphaComponent(0.3), for: .highlighted) + return button + }() + + private(set) lazy var pageViewController: UIPageViewController = { + let pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) + pageController.setViewControllers([WelcomeContentViewController(page: .whatIsMastodon)], direction: .forward, animated: false) + return pageController + }() + var currentPage: WelcomeContentPage = .whatIsMastodon + var currentPageOffset = 0 } extension WelcomeViewController { - - private func setupButtonShadowView() { - signUpButtonShadowView.layer.setupShadow( - color: .black, - alpha: 0.25, - x: 0, - y: 1, - blur: 2, - spread: 0, - roundedRect: signUpButtonShadowView.bounds, - byRoundingCorners: .allCorners, - cornerRadii: CGSize(width: 10, height: 10) - ) - } - - private func updateButtonContainerLayoutMargins(traitCollection: UITraitCollection) { - switch traitCollection.userInterfaceIdiom { - case .phone: - buttonContainer.layoutMargins = UIEdgeInsets( - top: 0, - left: WelcomeViewController.actionButtonMargin, - bottom: WelcomeViewController.viewBottomPaddingHeight, - right: WelcomeViewController.actionButtonMargin - ) - default: - let margin = traitCollection.horizontalSizeClass == .regular ? WelcomeViewController.actionButtonMarginExtend : WelcomeViewController.actionButtonMargin - buttonContainer.layoutMargins = UIEdgeInsets( - top: 0, - left: margin, - bottom: WelcomeViewController.viewBottomPaddingHeightExtend, - right: margin - ) + + override func viewDidLoad() { + super.viewDidLoad() + + definesPresentationContext = true + preferredContentSize = CGSize(width: 547, height: 678) + + navigationController?.navigationBar.prefersLargeTitles = true + view.overrideUserInterfaceStyle = .light + + setupOnboardingAppearance() + + view.addSubview(welcomeIllustrationView) + welcomeIllustrationView.translatesAutoresizingMaskIntoConstraints = false + + NSLayoutConstraint.activate([ + welcomeIllustrationView.topAnchor.constraint(equalTo: view.topAnchor), + welcomeIllustrationView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + view.trailingAnchor.constraint(equalTo: welcomeIllustrationView.trailingAnchor), + view.bottomAnchor.constraint(equalTo: welcomeIllustrationView.bottomAnchor) + ]) + + buttonContainer.axis = .vertical + buttonContainer.spacing = 12 + buttonContainer.isLayoutMarginsRelativeArrangement = true + + buttonContainer.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(buttonContainer) + NSLayoutConstraint.activate([ + buttonContainer.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor), + buttonContainer.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor), + view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: buttonContainer.bottomAnchor), + ]) + + signUpButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(signUpButton) + NSLayoutConstraint.activate([ + signUpButton.heightAnchor.constraint(greaterThanOrEqualToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), + ]) + signInButton.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addArrangedSubview(signInButton) + NSLayoutConstraint.activate([ + signInButton.heightAnchor.constraint(greaterThanOrEqualToConstant: WelcomeViewController.actionButtonHeight).priority(.required - 1), + ]) + + signUpButtonShadowView.translatesAutoresizingMaskIntoConstraints = false + buttonContainer.addSubview(signUpButtonShadowView) + buttonContainer.sendSubviewToBack(signUpButtonShadowView) + signUpButtonShadowView.pinTo(to: signUpButton) + + signUpButton.addTarget(self, action: #selector(signUpButtonDidClicked(_:)), for: .touchUpInside) + signInButton.addTarget(self, action: #selector(signInButtonDidClicked(_:)), for: .touchUpInside) + + pageViewController.delegate = self + pageViewController.dataSource = self + addChild(pageViewController) + pageViewController.view.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(pageViewController.view) + pageViewController.didMove(toParent: self) + + let scrollviews = pageViewController.view.subviews.filter { type(of: $0).isSubclass(of: UIScrollView.self) }.compactMap { $0 as? UIScrollView } + + for scrollView in scrollviews { + scrollView.delegate = self + } + + NSLayoutConstraint.activate([ + pageViewController.view.topAnchor.constraint(equalTo: view.topAnchor, constant: computedTopAnchorInset), + pageViewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + view.trailingAnchor.constraint(equalTo: pageViewController.view.trailingAnchor), + buttonContainer.topAnchor.constraint(equalTo: pageViewController.view.bottomAnchor, constant: 16), + ]) + + viewModel.$needsShowDismissEntry + .receive(on: DispatchQueue.main) + .sink { [weak self] needsShowDismissEntry in + guard let self = self else { return } + self.navigationItem.leftBarButtonItem = needsShowDismissEntry ? self.dismissBarButtonItem : nil + } + .store(in: &disposeBag) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + setupButtonShadowView() + } + + override func viewSafeAreaInsetsDidChange() { + super.viewSafeAreaInsetsDidChange() + + var overlap: CGFloat = 5 + // shift illustration down for non-notch phone + if view.safeAreaInsets.bottom == 0 { + overlap += 56 + } + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + view.layoutIfNeeded() + + setupIllustrationLayout() + setupButtonShadowView() + } + + private var computedTopAnchorInset: CGFloat { + (navigationController?.navigationBar.bounds.height ?? UINavigationBar().bounds.height) + Constants.topAnchorInset } - } - - private func setupIllustrationLayout() { - welcomeIllustrationView.setup() - } } extension WelcomeViewController { - @objc - private func signUpButtonDidClicked(_ sender: UIButton) { - _ = coordinator.present(scene: .mastodonPickServer(viewMode: MastodonPickServerViewModel(context: context)), from: self, transition: .show) - } + + private func setupButtonShadowView() { + signUpButtonShadowView.layer.setupShadow( + color: .black, + alpha: 0.25, + x: 0, + y: 1, + blur: 2, + spread: 0, + roundedRect: signUpButtonShadowView.bounds, + byRoundingCorners: .allCorners, + cornerRadii: CGSize(width: 10, height: 10) + ) + } + + private func updateButtonContainerLayoutMargins(traitCollection: UITraitCollection) { + switch traitCollection.userInterfaceIdiom { + case .phone: + buttonContainer.layoutMargins = UIEdgeInsets( + top: 0, + left: WelcomeViewController.actionButtonMargin, + bottom: WelcomeViewController.viewBottomPaddingHeight, + right: WelcomeViewController.actionButtonMargin + ) + default: + let margin = traitCollection.horizontalSizeClass == .regular ? WelcomeViewController.actionButtonMarginExtend : WelcomeViewController.actionButtonMargin + buttonContainer.layoutMargins = UIEdgeInsets( + top: 0, + left: margin, + bottom: WelcomeViewController.viewBottomPaddingHeightExtend, + right: margin + ) + } + } + + private func setupIllustrationLayout() { + welcomeIllustrationView.setup() + } +} - @objc - private func signInButtonDidClicked(_ sender: UIButton) { - _ = coordinator.present(scene: .mastodonLogin, from: self, transition: .show) - } - - @objc - private func dismissBarButtonItemDidPressed(_ sender: UIButton) { - dismiss(animated: true, completion: nil) - } +extension WelcomeViewController { + @objc + private func signUpButtonDidClicked(_ sender: UIButton) { + _ = coordinator.present(scene: .mastodonPickServer(viewMode: MastodonPickServerViewModel(context: context)), from: self, transition: .show) + } + + @objc + private func signInButtonDidClicked(_ sender: UIButton) { + _ = coordinator.present(scene: .mastodonLogin, from: self, transition: .show) + } + + @objc + private func dismissBarButtonItemDidPressed(_ sender: UIButton) { + dismiss(animated: true, completion: nil) + } } // MARK: - OnboardingViewControllerAppearance @@ -245,104 +253,104 @@ extension WelcomeViewController: OnboardingViewControllerAppearance { // MARK: - UIAdaptivePresentationControllerDelegate extension WelcomeViewController: UIAdaptivePresentationControllerDelegate { - - func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { - - // update button layout - updateButtonContainerLayoutMargins(traitCollection: traitCollection) - - let navigationController = navigationController as? OnboardingNavigationController - - switch traitCollection.userInterfaceIdiom { - case .phone: - navigationController?.gradientBorderView.isHidden = true - // make underneath view controller alive to fix layout issue due to view life cycle - return .fullScreen - default: - switch traitCollection.horizontalSizeClass { - case .compact: + + func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { + + // update button layout + updateButtonContainerLayoutMargins(traitCollection: traitCollection) + + let navigationController = navigationController as? OnboardingNavigationController + + switch traitCollection.userInterfaceIdiom { + case .phone: navigationController?.gradientBorderView.isHidden = true + // make underneath view controller alive to fix layout issue due to view life cycle return .fullScreen - default: - navigationController?.gradientBorderView.isHidden = false - return .formSheet + default: + switch traitCollection.horizontalSizeClass { + case .compact: + navigationController?.gradientBorderView.isHidden = true + return .fullScreen + default: + navigationController?.gradientBorderView.isHidden = false + return .formSheet + } } } - } - - func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { - return nil - } - - func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { - return false - } + + func presentationController(_ controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { + return nil + } + + func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { + return false + } } //MARK: - UIPageViewControllerDelegate extension WelcomeViewController: UIPageViewControllerDelegate { - func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { - guard let currentViewController = pageViewController.viewControllers?.first as? WelcomeContentViewController else { return } - - currentPage = currentViewController.page - - if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) { - let offset = Int(pageIndex) * Int(pageViewController.view.frame.width) - currentPageOffset = offset - welcomeIllustrationView.update(contentOffset: CGFloat(offset)) + func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { + guard let currentViewController = pageViewController.viewControllers?.first as? WelcomeContentViewController else { return } + + currentPage = currentViewController.page + + if let pageIndex = WelcomeContentPage.allCases.firstIndex(of: currentPage) { + let offset = Int(pageIndex) * Int(pageViewController.view.frame.width) + currentPageOffset = offset + welcomeIllustrationView.update(contentOffset: CGFloat(offset)) + } } - } } //MARK: - UIPageViewDataSource extension WelcomeViewController: UIPageViewControllerDataSource { - - func presentationIndex(for pageViewController: UIPageViewController) -> Int { - WelcomeContentPage.allCases.firstIndex(of: currentPage) ?? 0 - } - - func presentationCount(for pageViewController: UIPageViewController) -> Int { - return WelcomeContentPage.allCases.count - } - - func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { - guard let viewController = viewController as? WelcomeContentViewController else { return nil } - - let currentPage = viewController.page - - switch currentPage { - case .whatIsMastodon: - return nil - case .mastodonIsLikeThat: - return WelcomeContentViewController(page: .whatIsMastodon) - case .howDoIPickAServer: - return WelcomeContentViewController(page: .mastodonIsLikeThat) + + func presentationIndex(for pageViewController: UIPageViewController) -> Int { + WelcomeContentPage.allCases.firstIndex(of: currentPage) ?? 0 } - } - - func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { - guard let viewController = viewController as? WelcomeContentViewController else { return nil } - - let currentPage = viewController.page - - switch currentPage { - case .whatIsMastodon: - return WelcomeContentViewController(page: .mastodonIsLikeThat) - case .mastodonIsLikeThat: - return WelcomeContentViewController(page: .howDoIPickAServer) - case .howDoIPickAServer: - return nil + + func presentationCount(for pageViewController: UIPageViewController) -> Int { + return WelcomeContentPage.allCases.count + } + + func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { + guard let viewController = viewController as? WelcomeContentViewController else { return nil } + + let currentPage = viewController.page + + switch currentPage { + case .whatIsMastodon: + return nil + case .mastodonIsLikeThat: + return WelcomeContentViewController(page: .whatIsMastodon) + case .howDoIPickAServer: + return WelcomeContentViewController(page: .mastodonIsLikeThat) + } + } + + func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { + guard let viewController = viewController as? WelcomeContentViewController else { return nil } + + let currentPage = viewController.page + + switch currentPage { + case .whatIsMastodon: + return WelcomeContentViewController(page: .mastodonIsLikeThat) + case .mastodonIsLikeThat: + return WelcomeContentViewController(page: .howDoIPickAServer) + case .howDoIPickAServer: + return nil + } } - } } extension WelcomeViewController: UIScrollViewDelegate { - func scrollViewDidScroll(_ scrollView: UIScrollView) { - let weirdScrollViewJumpingCorrectionFactor = pageViewController.view.frame.width - let contentOffset = CGFloat(currentPageOffset) + scrollView.contentOffset.x - weirdScrollViewJumpingCorrectionFactor - - welcomeIllustrationView.update(contentOffset: contentOffset) - } + func scrollViewDidScroll(_ scrollView: UIScrollView) { + let weirdScrollViewJumpingCorrectionFactor = pageViewController.view.frame.width + let contentOffset = CGFloat(currentPageOffset) + scrollView.contentOffset.x - weirdScrollViewJumpingCorrectionFactor + + welcomeIllustrationView.update(contentOffset: contentOffset) + } }