Refactor tab/MainTabBarController to add viewcontrollers as properties
This is a WIP-step for account-stuff. Also: iPhone only, iPad should come next
This commit is contained in:
parent
cea6129229
commit
2c653320fb
|
@ -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 = "<group>"; };
|
||||
D8B5E4F32A4ED0240008970C /* NotificationSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsViewModel.swift; sourceTree = "<group>"; };
|
||||
D8BE30B22A179E26006B8270 /* SuggestionAccountTableViewFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionAccountTableViewFooter.swift; sourceTree = "<group>"; };
|
||||
D8CF45822B50893900C84D70 /* Tab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tab.swift; sourceTree = "<group>"; };
|
||||
D8D688F52AB869CB000F651A /* SearchResultsProfileTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsProfileTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D8D688F82AB8B970000F651A /* SearchResultOverviewCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultOverviewCoordinator.swift; sourceTree = "<group>"; };
|
||||
D8E5C345296DAB84007E76A7 /* DataSourceFacade+Status+History.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+Status+History.swift"; sourceTree = "<group>"; };
|
||||
|
@ -2557,6 +2559,7 @@
|
|||
DB03A794272A981400EE37C5 /* ContentSplitViewController.swift */,
|
||||
DB852D1A26FAED0100FC9D81 /* Sidebar */,
|
||||
DB8AF54E25C13703002E6C99 /* MainTab */,
|
||||
D8CF45822B50893900C84D70 /* Tab.swift */,
|
||||
);
|
||||
path = Root;
|
||||
sourceTree = "<group>";
|
||||
|
@ -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 */,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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<Section, Item>?
|
||||
|
@ -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<SidebarListCollectionViewCell, MainTabBarController.Tab> { [weak self] cell, indexPath, item in
|
||||
let tabCellRegistration = UICollectionView.CellRegistration<SidebarListCollectionViewCell, Tab> { [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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue