2
2
mirror of https://github.com/mastodon/mastodon-ios synced 2025-04-11 22:58:02 +02:00
mastodon-ios/Mastodon/Scene/Thread/ThreadViewController+DataSourceProvider.swift
shannon d2b4d7b6b4 Refactor: Filter and Content Warning display and management
A large amount of change primarily to the view model layer, to make reasoning about the content reveal/hide state easier.

To prevent terrible scrolling jags while allowing the cells to be shorter when hiding content, the layout changes for content display state now happen before the cell is returned by the datasource provider and the tableview is reloaded when a status’s display mode changes.
2024-11-28 13:08:01 -05:00

102 lines
3.5 KiB
Swift

//
// ThreadViewController+DataSourceProvider.swift
// Mastodon
//
// Created by MainasuK on 2022-1-17.
//
import UIKit
import MastodonSDK
// MARK: - DataSourceProvider
extension ThreadViewController: DataSourceProvider {
var filterContext: MastodonSDK.Mastodon.Entity.FilterContext? {
return .thread
}
func didToggleContentWarningDisplayStatus(status: MastodonSDK.MastodonStatus) {
tableView.reloadData()
}
func item(from source: DataSourceItem.Source) async -> DataSourceItem? {
var _indexPath = source.indexPath
if _indexPath == nil, let cell = source.tableViewCell {
_indexPath = await self.indexPath(for: cell)
}
guard let indexPath = _indexPath else { return nil }
guard let item = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else {
return nil
}
switch item {
case .thread(let thread):
return .status(record: thread.record)
default:
return nil
}
}
func update(status _status: MastodonStatus, intent: MastodonStatus.UpdateIntent) {
let status = _status.reblog ?? _status
if case MastodonStatus.UpdateIntent.delete = intent {
return handleDelete(status)
}
switch viewModel.root {
case let .root(context):
if context.status.id == status.id {
viewModel.root = .root(context: .init(status: status))
} else {
handleUpdate(status: status, viewModel: viewModel.mastodonStatusThreadViewModel, intent: intent)
}
case let .reply(context):
if context.status.id == status.id {
viewModel.root = .reply(context: .init(status: status))
} else {
handleUpdate(status: status, viewModel: viewModel.mastodonStatusThreadViewModel, intent: intent)
}
case let .leaf(context):
if context.status.id == status.id {
viewModel.root = .leaf(context: .init(status: status))
} else {
handleUpdate(status: status, viewModel: viewModel.mastodonStatusThreadViewModel, intent: intent)
}
case .none:
assertionFailure("This should not have happened")
}
}
private func handleDelete(_ status: MastodonStatus) {
if viewModel.root?.record.id == status.id {
viewModel.root = nil
viewModel.onDismiss.send(status)
}
viewModel.mastodonStatusThreadViewModel.handleDelete(status)
}
@MainActor
private func indexPath(for cell: UITableViewCell) async -> IndexPath? {
return tableView.indexPath(for: cell)
}
private func handleUpdate(status: MastodonStatus, viewModel: MastodonStatusThreadViewModel, intent: MastodonStatus.UpdateIntent) {
switch intent {
case .bookmark:
viewModel.handleBookmark(status)
case let .reblog(isReblogged):
viewModel.handleReblog(status, isReblogged)
case .favorite:
viewModel.handleFavorite(status)
case let .toggleSensitive(isVisible):
viewModel.handleSensitive(status, isVisible)
case .edit:
viewModel.handleEdit(status)
case .delete:
break // this case has already been handled
case .pollVote:
viewModel.handleEdit(status) // technically the data changed so refresh it to reflect the new data
}
}
}