mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-22 16:21:00 +00:00
145 lines
5.6 KiB
Swift
145 lines
5.6 KiB
Swift
// Copyright © 2021 Metabolist. All rights reserved.
|
|
|
|
import Combine
|
|
import SwiftUI
|
|
import ViewModels
|
|
|
|
final class MainNavigationViewController: UITabBarController {
|
|
private let viewModel: NavigationViewModel
|
|
private let rootViewModel: RootViewModel
|
|
private var cancellables = Set<AnyCancellable>()
|
|
private weak var presentedSecondaryNavigation: UINavigationController?
|
|
|
|
init(viewModel: NavigationViewModel, rootViewModel: RootViewModel) {
|
|
self.viewModel = viewModel
|
|
self.rootViewModel = rootViewModel
|
|
|
|
super.init(nibName: nil, bundle: nil)
|
|
}
|
|
|
|
@available(*, unavailable)
|
|
required init?(coder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
viewModel.$presentingSecondaryNavigation.sink { [weak self] in
|
|
if $0 {
|
|
self?.presentSecondaryNavigation()
|
|
} else {
|
|
self?.dismissSecondaryNavigation()
|
|
}
|
|
}
|
|
.store(in: &cancellables)
|
|
|
|
viewModel.identityContext.$identity.map(\.pending)
|
|
.removeDuplicates()
|
|
.print()
|
|
.sink { [weak self] in self?.setupViewControllers(pending: $0) }
|
|
.store(in: &cancellables)
|
|
|
|
viewModel.timelineNavigations.map { _ in }
|
|
.merge(with: viewModel.followRequestNavigations.map { _ in })
|
|
.sink { [weak self] in self?.selectedIndex = 0 }
|
|
.store(in: &cancellables)
|
|
|
|
NotificationCenter.default.publisher(for: UIScene.willEnterForegroundNotification)
|
|
.sink { [weak self] _ in self?.viewModel.refreshIdentity() }
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
override func viewWillAppear(_ animated: Bool) {
|
|
super.viewWillAppear(animated)
|
|
|
|
viewModel.refreshIdentity()
|
|
}
|
|
}
|
|
|
|
private extension MainNavigationViewController {
|
|
func setupViewControllers(pending: Bool) {
|
|
var controllers: [UIViewController] = [
|
|
TimelinesViewController(
|
|
viewModel: viewModel,
|
|
rootViewModel: rootViewModel),
|
|
ExploreViewController(
|
|
viewModel: viewModel.exploreViewModel(),
|
|
rootViewModel: rootViewModel)
|
|
]
|
|
|
|
if viewModel.identityContext.identity.authenticated && !pending {
|
|
controllers.append(NotificationsViewController(viewModel: viewModel, rootViewModel: rootViewModel))
|
|
|
|
let conversationsViewController = TableViewController(
|
|
viewModel: viewModel.conversationsViewModel(),
|
|
rootViewModel: rootViewModel)
|
|
|
|
conversationsViewController.tabBarItem = NavigationViewModel.Tab.messages.tabBarItem
|
|
conversationsViewController.navigationItem.title = NavigationViewModel.Tab.messages.title
|
|
|
|
controllers.append(conversationsViewController)
|
|
|
|
setupNewStatusButton()
|
|
}
|
|
|
|
let secondaryNavigationButton = SecondaryNavigationButton(viewModel: viewModel, rootViewModel: rootViewModel)
|
|
|
|
for controller in controllers {
|
|
controller.navigationItem.leftBarButtonItem = secondaryNavigationButton
|
|
}
|
|
|
|
viewControllers = controllers.map(UINavigationController.init(rootViewController:))
|
|
}
|
|
|
|
func setupNewStatusButton() {
|
|
let newStatusButtonView = NewStatusButtonView(primaryAction: UIAction { [weak self] _ in
|
|
guard let self = self else { return }
|
|
let newStatusViewModel = self.rootViewModel.newStatusViewModel(
|
|
identityContext: self.viewModel.identityContext)
|
|
let newStatusViewController = NewStatusViewController(viewModel: newStatusViewModel)
|
|
let newStatusNavigationController = UINavigationController(rootViewController: newStatusViewController)
|
|
|
|
if UIDevice.current.userInterfaceIdiom == .phone {
|
|
newStatusNavigationController.modalPresentationStyle = .overFullScreen
|
|
} else {
|
|
newStatusNavigationController.isModalInPresentation = true
|
|
}
|
|
|
|
self.present(newStatusNavigationController, animated: true)
|
|
})
|
|
|
|
view.addSubview(newStatusButtonView)
|
|
newStatusButtonView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
NSLayoutConstraint.activate([
|
|
newStatusButtonView.widthAnchor.constraint(equalToConstant: .newStatusButtonDimension),
|
|
newStatusButtonView.heightAnchor.constraint(equalToConstant: .newStatusButtonDimension),
|
|
newStatusButtonView.trailingAnchor.constraint(
|
|
equalTo: view.safeAreaLayoutGuide.trailingAnchor,
|
|
constant: -.defaultSpacing * 2),
|
|
newStatusButtonView.bottomAnchor.constraint(equalTo: tabBar.topAnchor, constant: -.defaultSpacing * 2)
|
|
])
|
|
}
|
|
|
|
func presentSecondaryNavigation() {
|
|
let secondaryNavigationView = SecondaryNavigationView(viewModel: viewModel)
|
|
.environmentObject(rootViewModel)
|
|
let hostingController = UIHostingController(rootView: secondaryNavigationView)
|
|
|
|
hostingController.navigationItem.leftBarButtonItem = UIBarButtonItem(
|
|
systemItem: .close,
|
|
primaryAction: UIAction { [weak self] _ in self?.viewModel.presentingSecondaryNavigation = false })
|
|
|
|
let navigationController = UINavigationController(rootViewController: hostingController)
|
|
|
|
presentedSecondaryNavigation = navigationController
|
|
present(navigationController, animated: true)
|
|
}
|
|
|
|
func dismissSecondaryNavigation() {
|
|
if presentedViewController == presentedSecondaryNavigation {
|
|
dismiss(animated: true)
|
|
}
|
|
}
|
|
}
|