diff --git a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift index 6d6e9d7eb..bae0d09e0 100644 --- a/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/AboutInstanceViewController.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit +import MastodonSDK protocol AboutInstanceViewControllerDelegate: AnyObject { @@ -11,8 +12,14 @@ class AboutInstanceViewController: UIViewController { init() { super.init(nibName: nil, bundle: nil) + + view.backgroundColor = .green } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func update(with instance: Mastodon.Entity.V2.Instance) { + //TODO: Implement + } } diff --git a/Mastodon/Scene/Settings/Server Details/InstanceRulesViewController.swift b/Mastodon/Scene/Settings/Server Details/InstanceRulesViewController.swift index e28802505..4e09097ac 100644 --- a/Mastodon/Scene/Settings/Server Details/InstanceRulesViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/InstanceRulesViewController.swift @@ -1,6 +1,7 @@ // Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit +import MastodonSDK protocol InstanceRulesViewControllerDelegate: AnyObject { @@ -11,7 +12,13 @@ class InstanceRulesViewController: UIViewController { init() { super.init(nibName: nil, bundle: nil) + + view.backgroundColor = .blue } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + func update(with instance: Mastodon.Entity.V2.Instance) { + //TODO: Implement + } } diff --git a/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift b/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift index 8fc8a114c..84357ea1c 100644 --- a/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift +++ b/Mastodon/Scene/Settings/Server Details/ServerDetailsViewController.swift @@ -1,6 +1,20 @@ // Copyright © 2023 Mastodon gGmbH. All rights reserved. import UIKit +import MastodonSDK + +enum ServerDetailsTab: Int, CaseIterable { + case about = 0 + case rules = 1 + + var title: String { + switch self { + //TODO: Add localization @zeitschlag + case .about: return "About" + case .rules: return "Rules" + } + } +} protocol ServerDetailsViewControllerDelegate: AnyObject { @@ -8,45 +22,129 @@ protocol ServerDetailsViewControllerDelegate: AnyObject { class ServerDetailsViewController: UIViewController { - weak var delegate: ServerDetailsViewControllerDelegate? - // PageController + weak var delegate: (ServerDetailsViewControllerDelegate & AboutInstanceViewControllerDelegate & InstanceRulesViewControllerDelegate)? { + didSet { + aboutInstanceViewController.delegate = delegate + instanceRulesViewController.delegate = delegate + } + } + let pageController: UIPageViewController + private let segmentedControlWrapper: UIView let segmentedControl: UISegmentedControl + let aboutInstanceViewController: AboutInstanceViewController + let instanceRulesViewController: InstanceRulesViewController let containerView: UIView - init() { + init(domain: String) { segmentedControl = UISegmentedControl() segmentedControl.translatesAutoresizingMaskIntoConstraints = false + segmentedControlWrapper = UIView() + segmentedControlWrapper.translatesAutoresizingMaskIntoConstraints = false + segmentedControlWrapper.addSubview(segmentedControl) + containerView = UIView() containerView.translatesAutoresizingMaskIntoConstraints = false - containerView.backgroundColor = .green + + aboutInstanceViewController = AboutInstanceViewController() + instanceRulesViewController = InstanceRulesViewController() + + pageController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal) + pageController.setViewControllers([aboutInstanceViewController], direction: .forward, animated: false) super.init(nibName: nil, bundle: nil) - view.addSubview(segmentedControl) + 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 } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupConstraints() { let constraints = [ - segmentedControl.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), - segmentedControl.leadingAnchor.constraint(equalTo: view.leadingAnchor), - view.trailingAnchor.constraint(equalTo: segmentedControl.trailingAnchor), + segmentedControlWrapper.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + segmentedControlWrapper.leadingAnchor.constraint(equalTo: view.leadingAnchor), + view.trailingAnchor.constraint(equalTo: segmentedControlWrapper.trailingAnchor), - containerView.topAnchor.constraint(equalTo: segmentedControl.bottomAnchor), + 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), ] 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) + } } +//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 + } + } +} diff --git a/Mastodon/Scene/Settings/SettingsCoordinator.swift b/Mastodon/Scene/Settings/SettingsCoordinator.swift index 2b3524655..6c8a46408 100644 --- a/Mastodon/Scene/Settings/SettingsCoordinator.swift +++ b/Mastodon/Scene/Settings/SettingsCoordinator.swift @@ -66,10 +66,18 @@ extension SettingsCoordinator: SettingsViewControllerDelegate { notificationViewController.delegate = self navigationController.pushViewController(notificationViewController, animated: true) - case .serverDetails(_): - let serverDetailsViewController = ServerDetailsViewController() + case .serverDetails(let domain): + let serverDetailsViewController = ServerDetailsViewController(domain: domain) serverDetailsViewController.delegate = self + appContext.apiService.instanceV2(domain: domain) + .sink { _ in + + } receiveValue: { content in + serverDetailsViewController.update(with: content.value) + } + .store(in: &disposeBag) + navigationController.pushViewController(serverDetailsViewController, animated: true) case .aboutMastodon: let aboutViewController = AboutViewController() @@ -139,6 +147,8 @@ extension SettingsCoordinator: NotificationSettingsViewControllerDelegate { guard viewModel.updated else { return } + //Show spinner? + let authenticationBox = authContext.mastodonAuthenticationBox guard let subscription = setting.activeSubscription, setting.domain == authenticationBox.domain, @@ -192,3 +202,11 @@ extension SettingsCoordinator: PolicySelectionViewControllerDelegate { extension SettingsCoordinator: ServerDetailsViewControllerDelegate { } + +extension SettingsCoordinator: AboutInstanceViewControllerDelegate { + +} + +extension SettingsCoordinator: InstanceRulesViewControllerDelegate { + +}