Fix context bugs

This commit is contained in:
Justin Mazzocchi 2020-08-23 21:34:19 -07:00
parent f340569295
commit 650e6b2991
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
5 changed files with 33 additions and 18 deletions

View file

@ -3,6 +3,7 @@
import Foundation import Foundation
enum StatusEndpoint { enum StatusEndpoint {
case status(id: String)
case favourite(id: String) case favourite(id: String)
case unfavourite(id: String) case unfavourite(id: String)
} }
@ -16,6 +17,8 @@ extension StatusEndpoint: MastodonEndpoint {
var pathComponentsInContext: [String] { var pathComponentsInContext: [String] {
switch self { switch self {
case let .status(id):
return [id]
case let .favourite(id): case let .favourite(id):
return [id, "favourite"] return [id, "favourite"]
case let .unfavourite(id): case let .unfavourite(id):
@ -25,6 +28,8 @@ extension StatusEndpoint: MastodonEndpoint {
var method: HTTPMethod { var method: HTTPMethod {
switch self { switch self {
case .status:
return .get
case .favourite, .unfavourite: case .favourite, .unfavourite:
return .post return .post
} }

View file

@ -6,7 +6,7 @@ import Combine
struct ContextService { struct ContextService {
let statusSections: AnyPublisher<[[Status]], Error> let statusSections: AnyPublisher<[[Status]], Error>
private var status: Status private let status: Status
private let context = CurrentValueSubject<MastodonContext, Never>(MastodonContext(ancestors: [], descendants: [])) private let context = CurrentValueSubject<MastodonContext, Never>(MastodonContext(ancestors: [], descendants: []))
private let networkClient: MastodonClient private let networkClient: MastodonClient
private let contentDatabase: ContentDatabase private let contentDatabase: ContentDatabase
@ -32,7 +32,7 @@ struct ContextService {
} }
extension ContextService: StatusListService { extension ContextService: StatusListService {
var contextParent: Status? { status } var contextParentID: String? { status.id }
func isReplyInContext(status: Status) -> Bool { func isReplyInContext(status: Status) -> Bool {
let flatContext = flattenedContext() let flatContext = flattenedContext()
@ -44,7 +44,7 @@ extension ContextService: StatusListService {
let previousStatus = flatContext[index - 1] let previousStatus = flatContext[index - 1]
return previousStatus.id != contextParent?.id && status.inReplyToId == previousStatus.id return previousStatus.id != contextParentID && status.inReplyToId == previousStatus.id
} }
func hasReplyFollowing(status: Status) -> Bool { func hasReplyFollowing(status: Status) -> Bool {
@ -57,14 +57,18 @@ extension ContextService: StatusListService {
let nextStatus = flatContext[index + 1] let nextStatus = flatContext[index + 1]
return status.id != contextParent?.id && nextStatus.inReplyToId == status.id return status.id != contextParentID && nextStatus.inReplyToId == status.id
} }
func request(maxID: String?, minID: String?) -> AnyPublisher<Void, Error> { func request(maxID: String?, minID: String?) -> AnyPublisher<Void, Error> {
Publishers.Merge(
networkClient.request(StatusEndpoint.status(id: status.id))
.map { ([$0], collection) }
.flatMap(contentDatabase.insert(statuses:collection:)),
networkClient.request(ContextEndpoint.context(id: status.id)) networkClient.request(ContextEndpoint.context(id: status.id))
.handleEvents(receiveOutput: context.send) .handleEvents(receiveOutput: context.send)
.map { ($0.ancestors + $0.descendants, collection) } .map { ($0.ancestors + $0.descendants, collection) }
.flatMap(contentDatabase.insert(statuses:collection:)) .flatMap(contentDatabase.insert(statuses:collection:)))
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }

View file

@ -5,7 +5,7 @@ import Combine
protocol StatusListService { protocol StatusListService {
var statusSections: AnyPublisher<[[Status]], Error> { get } var statusSections: AnyPublisher<[[Status]], Error> { get }
var contextParent: Status? { get } var contextParentID: String? { get }
func isPinned(status: Status) -> Bool func isPinned(status: Status) -> Bool
func isReplyInContext(status: Status) -> Bool func isReplyInContext(status: Status) -> Bool
func hasReplyFollowing(status: Status) -> Bool func hasReplyFollowing(status: Status) -> Bool
@ -15,7 +15,7 @@ protocol StatusListService {
} }
extension StatusListService { extension StatusListService {
var contextParent: Status? { nil } var contextParentID: String? { nil }
func isPinned(status: Status) -> Bool { false } func isPinned(status: Status) -> Bool { false }

View file

@ -26,7 +26,7 @@ class StatusesViewModel: ObservableObject {
} }
extension StatusesViewModel { extension StatusesViewModel {
var contextParent: Status? { statusListService.contextParent } var contextParentID: String? { statusListService.contextParentID }
func request(maxID: String? = nil, minID: String? = nil) { func request(maxID: String? = nil, minID: String? = nil) {
statusListService.request(maxID: maxID, minID: minID) statusListService.request(maxID: maxID, minID: minID)
@ -51,7 +51,7 @@ extension StatusesViewModel {
.sink {}) .sink {})
} }
statusViewModel.isContextParent = status == contextParent statusViewModel.isContextParent = status.id == contextParentID
statusViewModel.isPinned = statusListService.isPinned(status: status) statusViewModel.isPinned = statusListService.isPinned(status: status)
statusViewModel.isReplyInContext = statusListService.isReplyInContext(status: status) statusViewModel.isReplyInContext = statusListService.isReplyInContext(status: status)
statusViewModel.hasReplyFollowing = statusListService.hasReplyFollowing(status: status) statusViewModel.hasReplyFollowing = statusListService.hasReplyFollowing(status: status)
@ -69,8 +69,8 @@ private extension StatusesViewModel {
maintainScrollPositionOfStatusID = nil // clear old value maintainScrollPositionOfStatusID = nil // clear old value
// Maintain scroll position of parent after initial load of context // Maintain scroll position of parent after initial load of context
if let contextParent = contextParent, statusSections == [[], [contextParent], []] { if let contextParentID = contextParentID, statusSections.reduce([], +).map(\.id) == [contextParentID] {
maintainScrollPositionOfStatusID = contextParent.id maintainScrollPositionOfStatusID = contextParentID
} }
} }

View file

@ -101,7 +101,7 @@ class StatusListViewController: UITableViewController {
} }
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool { override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
viewModel.statusSections[indexPath.section][indexPath.row] != viewModel.contextParent viewModel.statusSections[indexPath.section][indexPath.row].id != viewModel.contextParentID
} }
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@ -123,11 +123,17 @@ extension StatusListViewController: StatusTableViewCellDelegate {
private extension StatusListViewController { private extension StatusListViewController {
func indexPath(statusID: String) -> IndexPath? { func indexPath(statusID: String) -> IndexPath? {
guard let status = viewModel.statusSections.reduce([], +).first(where: { $0.id == statusID }) else { for section in 0..<dataSource.numberOfSections(in: tableView) {
return nil for row in 0..<dataSource.tableView(tableView, numberOfRowsInSection: section) {
let indexPath = IndexPath(row: row, section: section)
if dataSource.itemIdentifier(for: indexPath)?.id == statusID {
return indexPath
}
}
} }
return dataSource.indexPath(for: status) return nil
} }
func share(url: URL) { func share(url: URL) {