// Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit import MastodonSDK import MastodonLocalization import MetaTextKit enum ServerDetailsTab: Int, CaseIterable { case about = 0 case rules = 1 var title: String { switch self { case .about: return L10n.Scene.Settings.ServerDetails.about case .rules: return L10n.Scene.Settings.ServerDetails.rules } } } protocol ServerDetailsViewControllerDelegate: AnyObject {} class ServerDetailsViewController: UIViewController { weak var delegate: (ServerDetailsViewControllerDelegate & AboutInstanceViewControllerDelegate & InstanceRulesViewControllerDelegate & MetaLabelDelegate)? { didSet { aboutInstanceViewController.delegate = delegate instanceRulesViewController.delegate = delegate aboutInstanceViewController.footerView.contentLabel.linkDelegate = delegate } } let pageController: UIPageViewController private let segmentedControlWrapper: UIView let segmentedControl: UISegmentedControl let aboutInstanceViewController: AboutInstanceViewController let instanceRulesViewController: InstanceRulesViewController let containerView: UIView init(domain: String) { segmentedControl = UISegmentedControl() segmentedControl.translatesAutoresizingMaskIntoConstraints = false segmentedControlWrapper = UIView() segmentedControlWrapper.translatesAutoresizingMaskIntoConstraints = false segmentedControlWrapper.addSubview(segmentedControl) containerView = UIView() containerView.translatesAutoresizingMaskIntoConstraints = false aboutInstanceViewController = AboutInstanceViewController() instanceRulesViewController = InstanceRulesViewController() pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) pageController.setViewControllers([aboutInstanceViewController], direction: .forward, animated: false) pageController.view.translatesAutoresizingMaskIntoConstraints = false super.init(nibName: nil, bundle: nil) view.addSubview(segmentedControlWrapper) view.addSubview(containerView) view.backgroundColor = .systemGroupedBackground containerView.addSubview(pageController.view) addChild(pageController) pageController.didMove(toParent: self) pageController.delegate = self pageController.dataSource = self ServerDetailsTab.allCases.forEach { segmentedControl.insertSegment(withTitle: $0.title, at: $0.rawValue, animated: false) } segmentedControl.selectedSegmentIndex = ServerDetailsTab.about.rawValue segmentedControl.addTarget(self, action: #selector(ServerDetailsViewController.segmentedControlValueChanged(_:)), for: .valueChanged) setupConstraints() title = domain setupNavigationBarAppearance() setupNavigationBarBackgroundView() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupConstraints() { let constraints = [ segmentedControlWrapper.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), segmentedControlWrapper.leadingAnchor.constraint(equalTo: view.leadingAnchor), view.trailingAnchor.constraint(equalTo: segmentedControlWrapper.trailingAnchor), containerView.topAnchor.constraint(equalTo: segmentedControlWrapper.bottomAnchor), containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor), view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), segmentedControl.topAnchor.constraint(equalTo: segmentedControlWrapper.topAnchor, constant: 4), segmentedControl.leadingAnchor.constraint(equalTo: segmentedControlWrapper.leadingAnchor, constant: 16), segmentedControlWrapper.trailingAnchor.constraint(equalTo: segmentedControl.trailingAnchor, constant: 16), segmentedControlWrapper.bottomAnchor.constraint(equalTo: segmentedControl.bottomAnchor, constant: 8), pageController.view.topAnchor.constraint(equalTo: containerView.topAnchor), pageController.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), containerView.trailingAnchor.constraint(equalTo: pageController.view.trailingAnchor), containerView.bottomAnchor.constraint(equalTo: pageController.view.bottomAnchor), ] NSLayoutConstraint.activate(constraints) } //MARK: - Actions @objc func segmentedControlValueChanged(_ sender: UISegmentedControl) { guard let selectedTab = ServerDetailsTab(rawValue: sender.selectedSegmentIndex) else { return } switch selectedTab { case .about: pageController.setViewControllers([aboutInstanceViewController], direction: .reverse, animated: true) case .rules: pageController.setViewControllers([instanceRulesViewController], direction: .forward, animated: true) } } func update(with instance: Mastodon.Entity.V2.Instance) { aboutInstanceViewController.update(with: instance) instanceRulesViewController.update(with: instance) } func updateFooter(with extendedDescription: Mastodon.Entity.ExtendedDescription) { aboutInstanceViewController.updateFooter(with: extendedDescription) } } //MARK: - UIPageViewControllerDataSource extension ServerDetailsViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { if viewController == instanceRulesViewController { return aboutInstanceViewController } else { return nil } } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { if viewController == aboutInstanceViewController { return instanceRulesViewController } else { return nil } } } //MARK: - UIPageViewControllerDelegate extension ServerDetailsViewController: UIPageViewControllerDelegate { func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { guard let currentViewController = pageViewController.viewControllers?.first else { return } if currentViewController == aboutInstanceViewController { segmentedControl.selectedSegmentIndex = ServerDetailsTab.about.rawValue } else if currentViewController == instanceRulesViewController { segmentedControl.selectedSegmentIndex = ServerDetailsTab.rules.rawValue } } } extension ServerDetailsViewController: OnboardingViewControllerAppearance {}