From 2c653320fbfed169fef2d4a6c9321a6bbe3b705e Mon Sep 17 00:00:00 2001 From: Nathan Mattes Date: Thu, 11 Jan 2024 23:36:13 +0100 Subject: [PATCH] Refactor tab/MainTabBarController to add viewcontrollers as properties This is a WIP-step for account-stuff. Also: iPhone only, iPad should come next --- Mastodon.xcodeproj/project.pbxproj | 4 + Mastodon/Coordinator/SceneCoordinator.swift | 2 +- .../Root/ContentSplitViewController.swift | 8 +- .../Root/MainTab/MainTabBarController.swift | 190 +++++------------- .../Scene/Root/RootSplitViewController.swift | 10 +- .../Root/Sidebar/SidebarViewController.swift | 2 +- .../Scene/Root/Sidebar/SidebarViewModel.swift | 8 +- Mastodon/Scene/Root/Tab.swift | 111 ++++++++++ 8 files changed, 180 insertions(+), 155 deletions(-) create mode 100644 Mastodon/Scene/Root/Tab.swift diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 02070824f..66cca4dd3 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -166,6 +166,7 @@ D8B5E4F22A4EBCF90008970C /* NotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B5E4F12A4EBCF90008970C /* NotificationSettings.swift */; }; D8B5E4F42A4ED0240008970C /* NotificationSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B5E4F32A4ED0240008970C /* NotificationSettingsViewModel.swift */; }; D8BE30B32A179E26006B8270 /* SuggestionAccountTableViewFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */; }; + D8CF45832B50893900C84D70 /* Tab.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CF45822B50893900C84D70 /* Tab.swift */; }; D8D688F62AB869CB000F651A /* SearchResultsProfileTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D688F52AB869CB000F651A /* SearchResultsProfileTableViewCell.swift */; }; D8D688F92AB8B970000F651A /* SearchResultOverviewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8D688F82AB8B970000F651A /* SearchResultOverviewCoordinator.swift */; }; D8E5C346296DAB84007E76A7 /* DataSourceFacade+Status+History.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */; }; @@ -833,6 +834,7 @@ D8B5E4F12A4EBCF90008970C /* NotificationSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettings.swift; sourceTree = ""; }; D8B5E4F32A4ED0240008970C /* NotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsViewModel.swift; sourceTree = ""; }; D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountTableViewFooter.swift; sourceTree = ""; }; + D8CF45822B50893900C84D70 /* Tab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab.swift; sourceTree = ""; }; D8D688F52AB869CB000F651A /* SearchResultsProfileTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsProfileTableViewCell.swift; sourceTree = ""; }; D8D688F82AB8B970000F651A /* SearchResultOverviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultOverviewCoordinator.swift; sourceTree = ""; }; D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+Status+History.swift"; sourceTree = ""; }; @@ -2557,6 +2559,7 @@ DB03A794272A981400EE37C5 /* ContentSplitViewController.swift */, DB852D1A26FAED0100FC9D81 /* Sidebar */, DB8AF54E25C13703002E6C99 /* MainTab */, + D8CF45822B50893900C84D70 /* Tab.swift */, ); path = Root; sourceTree = ""; @@ -3970,6 +3973,7 @@ 2A3F6FE5292F6E44002E6DA7 /* FollowedTagsTableViewCell.swift in Sources */, C24C97032922F30500BAE8CB /* RefreshControl.swift in Sources */, DB023D2A27A0FE5C005AC798 /* DataSourceProvider+NotificationTableViewCellDelegate.swift in Sources */, + D8CF45832B50893900C84D70 /* Tab.swift in Sources */, D8363B1629469CE200A74079 /* OnboardingNextView.swift in Sources */, DB98EB6027B10E150082E365 /* ReportCommentTableViewCell.swift in Sources */, DB0FCB962797E6C2006C02E2 /* SearchResultViewController+DataSourceProvider.swift in Sources */, diff --git a/Mastodon/Coordinator/SceneCoordinator.swift b/Mastodon/Coordinator/SceneCoordinator.swift index ef7f3b9cf..f2c7d4c6f 100644 --- a/Mastodon/Coordinator/SceneCoordinator.swift +++ b/Mastodon/Coordinator/SceneCoordinator.swift @@ -387,7 +387,7 @@ extension SceneCoordinator { return viewController } - func switchToTabBar(tab: MainTabBarController.Tab) { + func switchToTabBar(tab: Tab) { splitViewController?.contentSplitViewController.currentSupplementaryTab = tab splitViewController?.compactMainTabBarViewController.selectedIndex = tab.rawValue diff --git a/Mastodon/Scene/Root/ContentSplitViewController.swift b/Mastodon/Scene/Root/ContentSplitViewController.swift index fdc5b5ba3..68294739e 100644 --- a/Mastodon/Scene/Root/ContentSplitViewController.swift +++ b/Mastodon/Scene/Root/ContentSplitViewController.swift @@ -11,8 +11,8 @@ import CoreDataStack import MastodonCore protocol ContentSplitViewControllerDelegate: AnyObject { - func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) - func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didDoubleTapTab tab: MainTabBarController.Tab) + func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didSelectTab tab: Tab) + func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didDoubleTapTab tab: Tab) } final class ContentSplitViewController: UIViewController, NeedsDependency { @@ -37,7 +37,7 @@ final class ContentSplitViewController: UIViewController, NeedsDependency { return sidebarViewController }() - @Published var currentSupplementaryTab: MainTabBarController.Tab = .home + @Published var currentSupplementaryTab: Tab = .home private(set) lazy var mainTabBarController: MainTabBarController = { let mainTabBarController = MainTabBarController(context: context, coordinator: coordinator, authContext: authContext) if let homeTimelineViewController = mainTabBarController.viewController(of: HomeTimelineViewController.self) { @@ -102,7 +102,7 @@ extension ContentSplitViewController { // MARK: - SidebarViewControllerDelegate extension ContentSplitViewController: SidebarViewControllerDelegate { - func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) { + func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: Tab) { delegate?.contentSplitViewController(self, sidebarViewController: sidebarViewController, didSelectTab: tab) } diff --git a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift index 9012b7cad..6a3c54fb2 100644 --- a/Mastodon/Scene/Root/MainTab/MainTabBarController.swift +++ b/Mastodon/Scene/Root/MainTab/MainTabBarController.swift @@ -34,102 +34,13 @@ class MainTabBarController: UITabBarController { ) @Published var currentTab: Tab = .home - - enum Tab: Int, CaseIterable { - case home - case search - case compose - case notifications - case me - var tag: Int { - return rawValue - } - - var title: String { - switch self { - case .home: return L10n.Common.Controls.Tabs.home - case .search: return L10n.Common.Controls.Tabs.searchAndExplore - case .compose: return L10n.Common.Controls.Actions.compose - case .notifications: return L10n.Common.Controls.Tabs.notifications - case .me: return L10n.Common.Controls.Tabs.profile - } - } + let homeTimelineViewController: HomeTimelineViewController + let searchViewController: SearchViewController + let composeViewController: UIViewController // placeholder + let notificationViewController: NotificationViewController + let meProfileViewController: ProfileViewController - var inputLabels: [String]? { - switch self { - case .home, .compose, .notifications, .me: - return nil - case .search: - return [ - L10n.Common.Controls.Tabs.A11Y.search, - L10n.Common.Controls.Tabs.A11Y.explore, - L10n.Common.Controls.Tabs.searchAndExplore - ] - } - } - - var image: UIImage { - switch self { - case .home: return UIImage(systemName: "house")! - case .search: return UIImage(systemName: "magnifyingglass")! - case .compose: return UIImage(systemName: "square.and.pencil")! - case .notifications: return UIImage(systemName: "bell")! - case .me: return UIImage(systemName: "person")! - } - } - - var selectedImage: UIImage { - return image.withTintColor(Asset.Colors.Brand.blurple.color, renderingMode: .alwaysOriginal) - } - - var largeImage: UIImage { - return image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80)) - } - - @MainActor - func viewController(context: AppContext, authContext: AuthContext?, coordinator: SceneCoordinator) -> UIViewController { - guard let authContext else { return UITableViewController() } - - let viewController: UIViewController - switch self { - case .home: - let _viewController = HomeTimelineViewController() - _viewController.context = context - _viewController.coordinator = coordinator - _viewController.viewModel = HomeTimelineViewModel(context: context, authContext: authContext) - viewController = _viewController - case .search: - let _viewController = SearchViewController() - _viewController.context = context - _viewController.coordinator = coordinator - _viewController.viewModel = .init(context: context, authContext: authContext) - viewController = _viewController - case .compose: - viewController = UIViewController() - case .notifications: - let _viewController = NotificationViewController() - _viewController.context = context - _viewController.coordinator = coordinator - _viewController.viewModel = .init(context: context, authContext: authContext) - viewController = _viewController - case .me: - #warning("What happens if there's no me at the beginning? I guess we _do_ need another migration?") - guard let me = authContext.mastodonAuthenticationBox.authentication.account() else { return UIViewController() } - - let _viewController = ProfileViewController() - _viewController.context = context - _viewController.coordinator = coordinator - _viewController.viewModel = ProfileViewModel(context: context, authContext: authContext, account: me, relationship: nil, me: me) - viewController = _viewController - } - viewController.title = self.title - return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) - } - } - - var _viewControllers: [UIViewController] = [] - private(set) var isReadyForWizardAvatarButton = false // output @@ -146,15 +57,43 @@ class MainTabBarController: UITabBarController { self.context = context self.coordinator = coordinator self.authContext = authContext + + homeTimelineViewController = HomeTimelineViewController() + homeTimelineViewController.configureTabBarItem(with: .home) + homeTimelineViewController.context = context + homeTimelineViewController.coordinator = coordinator + + searchViewController = SearchViewController() + searchViewController.configureTabBarItem(with: .search) + searchViewController.context = context + searchViewController.coordinator = coordinator + + composeViewController = UIViewController() + composeViewController.configureTabBarItem(with: .compose) + + notificationViewController = NotificationViewController() + notificationViewController.configureTabBarItem(with: .notifications) + notificationViewController.context = context + notificationViewController.coordinator = coordinator + + meProfileViewController = ProfileViewController() + meProfileViewController.context = context + meProfileViewController.coordinator = coordinator + meProfileViewController.configureTabBarItem(with: .me) + + if let authContext { + notificationViewController.viewModel = NotificationViewModel(context: context, authContext: authContext) + homeTimelineViewController.viewModel = HomeTimelineViewModel(context: context, authContext: authContext) + searchViewController.viewModel = SearchViewModel(context: context, authContext: authContext) + } + super.init(nibName: nil, bundle: nil) + + viewControllers = [homeTimelineViewController, searchViewController, composeViewController, notificationViewController, meProfileViewController].map { AdaptiveStatusBarStyleNavigationController(rootViewController: $0) } tabBar.addInteraction(largeContentViewerInteraction) - - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") } + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension MainTabBarController { @@ -171,26 +110,9 @@ extension MainTabBarController { view.backgroundColor = .systemBackground // seealso: `ThemeService.apply(theme:)` - let tabs = Tab.allCases - var viewControllers = [UIViewController]() - - for tab in tabs { - let viewController = tab.viewController(context: context, authContext: authContext, coordinator: coordinator) - viewController.tabBarItem.tag = tab.tag - viewController.tabBarItem.title = tab.title // needs for acessiblity large content label - viewController.tabBarItem.image = tab.image.imageWithoutBaseline() - viewController.tabBarItem.largeContentSizeImage = tab.largeImage.imageWithoutBaseline() - viewController.tabBarItem.accessibilityLabel = tab.title - viewController.tabBarItem.accessibilityUserInputLabels = tab.inputLabels - viewController.tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) - viewControllers.append(viewController) - } - - _viewControllers = viewControllers setViewControllers(viewControllers, animated: false) selectedIndex = 0 - // hacky workaround for FB11986255 (Setting accessibilityUserInputLabels on a UITabBarItem has no effect) DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(50)) { if let searchItem = self.tabBar.subviews.first(where: { $0.accessibilityLabel == Tab.search.title }) { @@ -201,7 +123,7 @@ extension MainTabBarController { context.apiService.error .receive(on: DispatchQueue.main) .sink { [weak self] error in - guard let self = self, let coordinator = self.coordinator else { return } + guard let self, let coordinator = self.coordinator else { return } switch error { case .implicit: break @@ -228,15 +150,14 @@ extension MainTabBarController { ) .receive(on: DispatchQueue.main) .sink { [weak self] authentication, currentTab in - guard let self = self else { return } - guard let notificationViewController = self.notificationViewController else { return } - + guard let self else { return } + let authentication = self.authContext?.mastodonAuthenticationBox.userAuthorization let hasUnreadPushNotification: Bool = authentication.flatMap { authentication in let count = UserDefaults.shared.getNotificationCountWithAccessToken(accessToken: authentication.accessToken) return count > 0 } ?? false - + let image: UIImage if hasUnreadPushNotification { let imageConfiguration = UIImage.SymbolConfiguration(paletteColors: [.red, SystemTheme.tabBarItemNormalIconColor]) @@ -244,17 +165,18 @@ extension MainTabBarController { } else { image = Tab.notifications.image } - + notificationViewController.tabBarItem.image = image.imageWithoutBaseline() notificationViewController.navigationController?.tabBarItem.image = image.imageWithoutBaseline() } .store(in: &disposeBag) + layoutAvatarButton() - + $avatarURL .receive(on: DispatchQueue.main) .sink { [weak self] avatarURL in - guard let self = self else { return } + guard let self else { return } self.avatarButton.avatarImageView.setImage( url: avatarURL, placeholder: .placeholder(color: .systemFill), @@ -262,7 +184,7 @@ extension MainTabBarController { ) } .store(in: &disposeBag) - + NotificationCenter.default.publisher(for: .userFetched) .receive(on: DispatchQueue.main) .sink { [weak self] _ in @@ -300,11 +222,11 @@ extension MainTabBarController { $currentTab .receive(on: DispatchQueue.main) .sink { [weak self] tab in - guard let self = self else { return } + guard let self else { return } self.updateAvatarButtonAppearance() } .store(in: &disposeBag) - + updateTabBarDisplay() } @@ -358,7 +280,7 @@ extension MainTabBarController { case .search: assert(Thread.isMainThread) // double tapping search tab opens the search bar without additional taps - searchViewController?.searchBar.becomeFirstResponder() + searchViewController.searchBar.becomeFirstResponder() default: break } @@ -460,18 +382,6 @@ extension MainTabBarController { } } -extension MainTabBarController { - - var notificationViewController: NotificationViewController? { - return viewController(of: NotificationViewController.self) - } - - var searchViewController: SearchViewController? { - return viewController(of: SearchViewController.self) - } - -} - // MARK: - UITabBarControllerDelegate extension MainTabBarController: UITabBarControllerDelegate { func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index ea87f2500..8a6a88dfd 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -127,8 +127,8 @@ extension RootSplitViewController { // MARK: - ContentSplitViewControllerDelegate extension RootSplitViewController: ContentSplitViewControllerDelegate { - func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) { - guard let _ = MainTabBarController.Tab.allCases.firstIndex(of: tab) else { + func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didSelectTab tab: Tab) { + guard let _ = Tab.allCases.firstIndex(of: tab) else { assertionFailure() return } @@ -158,8 +158,8 @@ extension RootSplitViewController: ContentSplitViewControllerDelegate { } } - func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didDoubleTapTab tab: MainTabBarController.Tab) { - guard let _ = MainTabBarController.Tab.allCases.firstIndex(of: tab) else { + func contentSplitViewController(_ contentSplitViewController: ContentSplitViewController, sidebarViewController: SidebarViewController, didDoubleTapTab tab: Tab) { + guard let _ = Tab.allCases.firstIndex(of: tab) else { assertionFailure() return } @@ -170,7 +170,7 @@ extension RootSplitViewController: ContentSplitViewControllerDelegate { guard !isPrimaryDisplay else { return } - contentSplitViewController.mainTabBarController.searchViewController?.searchBar.becomeFirstResponder() + contentSplitViewController.mainTabBarController.searchViewController.searchBar.becomeFirstResponder() default: break } diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift index b9a7d80f1..e13fa8443 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift @@ -12,7 +12,7 @@ import MastodonCore import MastodonUI protocol SidebarViewControllerDelegate: AnyObject { - func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab) + func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: Tab) func sidebarViewController(_ sidebarViewController: SidebarViewController, didLongPressItem item: SidebarViewModel.Item, sourceView: UIView) func sidebarViewController(_ sidebarViewController: SidebarViewController, didDoubleTapItem item: SidebarViewModel.Item, sourceView: UIView) } diff --git a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift index 84b7f1cba..85c47fc42 100644 --- a/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift +++ b/Mastodon/Scene/Root/Sidebar/SidebarViewModel.swift @@ -23,7 +23,7 @@ final class SidebarViewModel { let authContext: AuthContext? @Published private var isSidebarDataSourceReady = false @Published private var isAvatarButtonDataReady = false - @Published var currentTab: MainTabBarController.Tab = .home + @Published var currentTab: Tab = .home // output var diffableDataSource: UICollectionViewDiffableDataSource? @@ -57,7 +57,7 @@ extension SidebarViewModel { } enum Item: Hashable { - case tab(MainTabBarController.Tab) + case tab(Tab) case setting case compose } @@ -69,7 +69,7 @@ extension SidebarViewModel { collectionView: UICollectionView, secondaryCollectionView: UICollectionView ) { - let tabCellRegistration = UICollectionView.CellRegistration { [weak self] cell, indexPath, item in + let tabCellRegistration = UICollectionView.CellRegistration { [weak self] cell, indexPath, item in guard let self else { return } let imageURL: URL? @@ -125,7 +125,7 @@ extension SidebarViewModel { let imageConfiguration = UIImage.SymbolConfiguration(paletteColors: [.red, SystemTheme.tabBarItemNormalIconColor]) image = UIImage(systemName: "bell.badge", withConfiguration: imageConfiguration)! } else { - image = MainTabBarController.Tab.notifications.image + image = Tab.notifications.image } cell.item?.image = image cell.item?.activeImage = image.withTintColor(Asset.Colors.Brand.blurple.color, renderingMode: .alwaysOriginal) diff --git a/Mastodon/Scene/Root/Tab.swift b/Mastodon/Scene/Root/Tab.swift new file mode 100644 index 000000000..a3303ba4e --- /dev/null +++ b/Mastodon/Scene/Root/Tab.swift @@ -0,0 +1,111 @@ +// Copyright © 2024 Mastodon gGmbH. All rights reserved. + +import UIKit +import MastodonLocalization +import MastodonAsset + +enum Tab: Int, CaseIterable { + case home + case search + case compose + case notifications + case me + + var tag: Int { + return rawValue + } + + var title: String { + switch self { + case .home: return L10n.Common.Controls.Tabs.home + case .search: return L10n.Common.Controls.Tabs.searchAndExplore + case .compose: return L10n.Common.Controls.Actions.compose + case .notifications: return L10n.Common.Controls.Tabs.notifications + case .me: return L10n.Common.Controls.Tabs.profile + } + } + + var inputLabels: [String]? { + switch self { + case .home, .compose, .notifications, .me: + return nil + case .search: + return [ + L10n.Common.Controls.Tabs.A11Y.search, + L10n.Common.Controls.Tabs.A11Y.explore, + L10n.Common.Controls.Tabs.searchAndExplore + ] + } + } + + var image: UIImage { + switch self { + case .home: return UIImage(systemName: "house")! + case .search: return UIImage(systemName: "magnifyingglass")! + case .compose: return UIImage(systemName: "square.and.pencil")! + case .notifications: return UIImage(systemName: "bell")! + case .me: return UIImage(systemName: "person")! + } + } + + var selectedImage: UIImage { + return image.withTintColor(Asset.Colors.Brand.blurple.color, renderingMode: .alwaysOriginal) + } + + var largeImage: UIImage { + return image.withRenderingMode(.alwaysTemplate).resized(size: CGSize(width: 80, height: 80)) + } + +// @MainActor +// func viewController(context: AppContext, authContext: AuthContext?, coordinator: SceneCoordinator) -> UIViewController { +// guard let authContext else { return UITableViewController() } +// +// let viewController: UIViewController +// switch self { +// case .home: +// let _viewController = HomeTimelineViewController() +// _viewController.context = context +// _viewController.coordinator = coordinator +// _viewController.viewModel = HomeTimelineViewModel(context: context, authContext: authContext) +// viewController = _viewController +// case .search: +// let _viewController = SearchViewController() +// _viewController.context = context +// _viewController.coordinator = coordinator +// _viewController.viewModel = SearchViewModel(context: context, authContext: authContext) +// viewController = _viewController +// case .compose: +// viewController = UIViewController() +// case .notifications: +// let _viewController = NotificationViewController() +// _viewController.context = context +// _viewController.coordinator = coordinator +// _viewController.viewModel = NotificationViewModel(context: context, authContext: authContext) +// viewController = _viewController +// case .me: +// #warning("What happens if there's no me at the beginning? I guess we _do_ need another migration?") +// guard let me = authContext.mastodonAuthenticationBox.authentication.account() else { return UIViewController() } +// +// let _viewController = ProfileViewController() +// _viewController.context = context +// _viewController.coordinator = coordinator +// _viewController.viewModel = ProfileViewModel(context: context, authContext: authContext, account: me, relationship: nil, me: me) +// viewController = _viewController +// } +// viewController.title = self.title +// return AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) +// } +} + +extension UIViewController { + func configureTabBarItem(with tab: Tab) { + title = tab.title + tabBarItem.tag = tab.tag + tabBarItem.title = tab.title // needs for acessiblity large content label + tabBarItem.image = tab.image.imageWithoutBaseline() + tabBarItem.largeContentSizeImage = tab.largeImage.imageWithoutBaseline() + tabBarItem.accessibilityLabel = tab.title + tabBarItem.accessibilityUserInputLabels = tab.inputLabels + tabBarItem.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) + } +}