// // ReportSection.swift // Mastodon // // Created by ihugo on 2021/4/20. // import Combine import CoreData import CoreDataStack import Foundation import MastodonSDK import UIKit import os.log import MastodonAsset import MastodonCore import MastodonLocalization enum ReportSection: Equatable, Hashable { case main } extension ReportSection { struct Configuration { } static func diffableDataSource( tableView: UITableView, context: AppContext, configuration: Configuration ) -> UITableViewDiffableDataSource { tableView.register(ReportHeadlineTableViewCell.self, forCellReuseIdentifier: String(describing: ReportHeadlineTableViewCell.self)) tableView.register(ReportStatusTableViewCell.self, forCellReuseIdentifier: String(describing: ReportStatusTableViewCell.self)) tableView.register(ReportCommentTableViewCell.self, forCellReuseIdentifier: String(describing: ReportCommentTableViewCell.self)) tableView.register(ReportResultActionTableViewCell.self, forCellReuseIdentifier: String(describing: ReportResultActionTableViewCell.self)) tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) return UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in switch item { case .header(let headerContext): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportHeadlineTableViewCell.self), for: indexPath) as! ReportHeadlineTableViewCell cell.primaryLabel.text = headerContext.primaryLabelText cell.secondaryLabel.text = headerContext.secondaryLabelText return cell case .status(let record): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportStatusTableViewCell.self), for: indexPath) as! ReportStatusTableViewCell context.managedObjectContext.performAndWait { guard let status = record.object(in: context.managedObjectContext) else { return } configure( context: context, tableView: tableView, cell: cell, viewModel: .init(value: status), configuration: configuration ) } return cell case .comment(let commentContext): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportCommentTableViewCell.self), for: indexPath) as! ReportCommentTableViewCell cell.commentTextView.text = commentContext.comment NotificationCenter.default.publisher(for: UITextView.textDidChangeNotification, object: cell.commentTextView) .receive(on: DispatchQueue.main) .sink { [weak cell] notification in guard let cell = cell else { return } commentContext.comment = cell.commentTextView.text // fix shadow get animation issue when cell height changes UIView.performWithoutAnimation { tableView.beginUpdates() tableView.endUpdates() } } .store(in: &cell.disposeBag) return cell case .result(let record): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ReportResultActionTableViewCell.self), for: indexPath) as! ReportResultActionTableViewCell context.managedObjectContext.performAndWait { guard let user = record.object(in: context.managedObjectContext) else { return } cell.avatarImageView.configure(configuration: .init(url: user.avatarImageURL())) } return cell case .bottomLoader: let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell cell.activityIndicatorView.startAnimating() return cell } } } } extension ReportSection { static func configure( context: AppContext, tableView: UITableView, cell: ReportStatusTableViewCell, viewModel: ReportStatusTableViewCell.ViewModel, configuration: Configuration ) { StatusSection.setupStatusPollDataSource( context: context, statusView: cell.statusView ) context.authenticationService.activeMastodonAuthenticationBox .map { $0 as UserIdentifier? } .assign(to: \.userIdentifier, on: cell.statusView.viewModel) .store(in: &cell.disposeBag) cell.configure( tableView: tableView, viewModel: viewModel ) } }