mastodon-ios/Mastodon/Scene/Thread/ThreadViewController.swift

197 lines
7.7 KiB
Swift
Raw Normal View History

2021-04-13 13:46:42 +02:00
//
// ThreadViewController.swift
// Mastodon
//
// Created by MainasuK Cirno on 2021-4-12.
//
import os.log
import UIKit
import Combine
import CoreData
import AVKit
2021-07-23 13:10:27 +02:00
import MastodonMeta
import MastodonAsset
import MastodonLocalization
2021-04-13 13:46:42 +02:00
final class ThreadViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
let logger = Logger(subsystem: "ThreadViewController", category: "ViewController")
2021-04-13 13:46:42 +02:00
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
var disposeBag = Set<AnyCancellable>()
var viewModel: ThreadViewModel!
let mediaPreviewTransitionController = MediaPreviewTransitionController()
2021-04-13 13:46:42 +02:00
let titleView = DoubleTitleLabelNavigationBarTitleView()
let replyBarButtonItem = AdaptiveUserInterfaceStyleBarButtonItem(
lightImage: UIImage(systemName: "arrowshape.turn.up.left")!,
darkImage: UIImage(systemName: "arrowshape.turn.up.left.fill")!
)
let tableView: UITableView = {
let tableView = ControlContainableTableView()
tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self))
tableView.register(TimelineMiddleLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineMiddleLoaderTableViewCell.self))
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
tableView.register(ThreadReplyLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: ThreadReplyLoaderTableViewCell.self))
tableView.rowHeight = UITableView.automaticDimension
tableView.separatorStyle = .none
tableView.backgroundColor = .clear
return tableView
}()
deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function)
}
}
extension ThreadViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor
2021-07-05 10:07:17 +02:00
ThemeService.shared.currentTheme
.receive(on: DispatchQueue.main)
2021-07-05 10:07:17 +02:00
.sink { [weak self] theme in
guard let self = self else { return }
self.view.backgroundColor = theme.secondarySystemBackgroundColor
}
.store(in: &disposeBag)
2021-04-13 13:46:42 +02:00
navigationItem.title = L10n.Scene.Thread.backTitle
navigationItem.titleView = titleView
navigationItem.rightBarButtonItem = replyBarButtonItem
replyBarButtonItem.button.addTarget(self, action: #selector(ThreadViewController.replyBarButtonItemPressed(_:)), for: .touchUpInside)
viewModel.$navigationBarTitle
.receive(on: DispatchQueue.main)
.sink { [weak self] title in
guard let self = self else { return }
guard let title = title else {
self.titleView.update(title: "", subtitle: nil)
return
}
self.titleView.update(titleMetaContent: title, subtitle: nil)
}
.store(in: &disposeBag)
2021-04-13 13:46:42 +02:00
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.topAnchor.constraint(equalTo: view.topAnchor),
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
tableView.delegate = self
viewModel.setupDiffableDataSource(
tableView: tableView,
statusTableViewCellDelegate: self
2021-07-23 13:10:27 +02:00
)
2021-04-13 13:46:42 +02:00
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
tableView.deselectRow(with: transitionCoordinator, animated: animated)
2021-04-13 13:46:42 +02:00
}
}
extension ThreadViewController {
@objc private func replyBarButtonItemPressed(_ sender: UIBarButtonItem) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
guard case let .root(threadContext) = viewModel.root else { return }
guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return }
let composeViewModel = ComposeViewModel(
context: context,
composeKind: .reply(status: threadContext.status),
authenticationBox: authenticationBox
)
coordinator.present(
scene: .compose(viewModel: composeViewModel),
from: self,
transition: .modal(animated: true, completion: nil)
)
2021-04-13 13:46:42 +02:00
}
}
//// MARK: - StatusTableViewControllerAspect
//extension ThreadViewController: StatusTableViewControllerAspect { }
2021-04-13 13:46:42 +02:00
// MARK: - UITableViewDelegate
extension ThreadViewController: UITableViewDelegate, AutoGenerateTableViewDelegate {
// sourcery:inline:ThreadViewController.AutoGenerateTableViewDelegate
2021-04-13 13:46:42 +02:00
// Generated using Sourcery
// DO NOT EDIT
2021-04-13 13:46:42 +02:00
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
aspectTableView(tableView, didSelectRowAt: indexPath)
}
2021-04-30 13:28:06 +02:00
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point)
}
2021-04-30 13:28:06 +02:00
func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration)
}
func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration)
}
2021-04-30 13:28:06 +02:00
func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator)
}
// sourcery:end
2021-04-30 13:28:06 +02:00
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
guard let diffableDataSource = viewModel.diffableDataSource else { return nil }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil }
switch item {
case .thread(let thread):
switch thread {
case .root:
return nil
default:
return indexPath
}
default:
return indexPath
}
2021-04-13 13:46:42 +02:00
}
}
// MARK: - StatusTableViewCellDelegate
extension ThreadViewController: StatusTableViewCellDelegate { }
2021-04-13 13:46:42 +02:00
extension ThreadViewController {
override var keyCommands: [UIKeyCommand]? {
return navigationKeyCommands + statusNavigationKeyCommands
}
}
// MARK: - StatusTableViewControllerNavigateable
extension ThreadViewController: StatusTableViewControllerNavigateable {
@objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) {
navigateKeyCommandHandler(sender)
}
@objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) {
statusKeyCommandHandler(sender)
}
}