mastodon-ios/Mastodon/Scene/Root/Sidebar/SidebarViewController.swift

164 lines
7.0 KiB
Swift
Raw Normal View History

2021-09-22 13:08:09 +02:00
//
// SidebarViewController.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-9-22.
//
2021-09-24 13:58:50 +02:00
import os.log
2021-09-22 13:08:09 +02:00
import UIKit
import Combine
import CoreDataStack
protocol SidebarViewControllerDelegate: AnyObject {
func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectTab tab: MainTabBarController.Tab)
func sidebarViewController(_ sidebarViewController: SidebarViewController, didSelectSearchHistory searchHistoryViewModel: SidebarViewModel.SearchHistoryViewModel)
2021-09-22 13:08:09 +02:00
}
final class SidebarViewController: UIViewController, NeedsDependency {
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
var disposeBag = Set<AnyCancellable>()
var viewModel: SidebarViewModel!
weak var delegate: SidebarViewControllerDelegate?
2021-09-24 13:58:50 +02:00
let settingBarButtonItem: UIBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.tintColor = Asset.Colors.brandBlue.color
barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate)
return barButtonItem
}()
2021-09-22 13:08:09 +02:00
static func createLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout() { (sectionIndex, layoutEnvironment) -> NSCollectionLayoutSection? in
2021-09-24 13:58:50 +02:00
var configuration = UICollectionLayoutListConfiguration(appearance: .sidebar)
configuration.backgroundColor = .clear
if sectionIndex == SidebarViewModel.Section.tab.rawValue {
// with indentation
configuration.headerMode = .none
} else {
// remove indentation
configuration.headerMode = .firstItemInSection
}
2021-09-22 13:08:09 +02:00
configuration.showsSeparators = false
let section = NSCollectionLayoutSection.list(using: configuration, layoutEnvironment: layoutEnvironment)
return section
}
return layout
}
let collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: SidebarViewController.createLayout())
collectionView.backgroundColor = .clear
return collectionView
}()
}
extension SidebarViewController {
override func viewDidLoad() {
super.viewDidLoad()
2021-09-24 13:58:50 +02:00
viewModel.context.authenticationService.activeMastodonAuthenticationBox
.receive(on: DispatchQueue.main)
.sink { [weak self] activeMastodonAuthenticationBox in
guard let self = self else { return }
let domain = activeMastodonAuthenticationBox?.domain
self.navigationItem.backBarButtonItem = {
let barButtonItem = UIBarButtonItem()
barButtonItem.image = UIImage(systemName: "sidebar.leading")
return barButtonItem
}()
2021-09-24 13:58:50 +02:00
self.navigationItem.title = domain
}
.store(in: &disposeBag)
navigationItem.rightBarButtonItem = settingBarButtonItem
settingBarButtonItem.target = self
settingBarButtonItem.action = #selector(SidebarViewController.settingBarButtonItemPressed(_:))
2021-09-22 13:08:09 +02:00
navigationController?.navigationBar.prefersLargeTitles = true
2021-09-24 13:58:50 +02:00
setupBackground(theme: ThemeService.shared.currentTheme.value)
ThemeService.shared.currentTheme
.receive(on: DispatchQueue.main)
.sink { [weak self] theme in
guard let self = self else { return }
self.setupBackground(theme: theme)
}
.store(in: &disposeBag)
2021-09-22 13:08:09 +02:00
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
collectionView.delegate = self
viewModel.setupDiffableDataSource(collectionView: collectionView)
}
2021-09-24 13:58:50 +02:00
private func setupBackground(theme: Theme) {
let color: UIColor = theme.sidebarBackgroundColor
2021-09-24 13:58:50 +02:00
let barAppearance = UINavigationBarAppearance()
barAppearance.configureWithOpaqueBackground()
barAppearance.backgroundColor = color
2021-09-24 13:58:50 +02:00
barAppearance.shadowColor = .clear
barAppearance.shadowImage = UIImage() // remove separator line
navigationItem.standardAppearance = barAppearance
navigationItem.compactAppearance = barAppearance
navigationItem.scrollEdgeAppearance = barAppearance
if #available(iOS 15.0, *) {
navigationItem.compactScrollEdgeAppearance = barAppearance
} else {
// Fallback on earlier versions
}
2021-09-24 13:58:50 +02:00
view.backgroundColor = color
collectionView.backgroundColor = color
2021-09-24 13:58:50 +02:00
}
}
extension SidebarViewController {
@objc private func settingBarButtonItemPressed(_ sender: UIBarButtonItem) {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
guard let setting = context.settingService.currentSetting.value else { return }
let settingsViewModel = SettingsViewModel(context: context, setting: setting)
coordinator.present(scene: .settings(viewModel: settingsViewModel), from: self, transition: .modal(animated: true, completion: nil))
}
2021-09-22 13:08:09 +02:00
}
// MARK: - UICollectionViewDelegate
extension SidebarViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let diffableDataSource = viewModel.diffableDataSource else { return }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return }
switch item {
case .tab(let tab):
delegate?.sidebarViewController(self, didSelectTab: tab)
case .searchHistory(let viewModel):
delegate?.sidebarViewController(self, didSelectSearchHistory: viewModel)
case .header:
break
2021-09-22 13:08:09 +02:00
case .account(let viewModel):
assert(Thread.isMainThread)
let authentication = context.managedObjectContext.object(with: viewModel.authenticationObjectID) as! MastodonAuthentication
context.authenticationService.activeMastodonUser(domain: authentication.domain, userID: authentication.userID)
.receive(on: DispatchQueue.main)
.sink { [weak self] result in
guard let self = self else { return }
self.coordinator.setup()
}
.store(in: &disposeBag)
case .addAccount:
coordinator.present(scene: .welcome, from: self, transition: .modal(animated: true, completion: nil))
}
}
}