Fix context bugs
This commit is contained in:
parent
f340569295
commit
650e6b2991
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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> {
|
||||||
networkClient.request(ContextEndpoint.context(id: status.id))
|
Publishers.Merge(
|
||||||
.handleEvents(receiveOutput: context.send)
|
networkClient.request(StatusEndpoint.status(id: status.id))
|
||||||
.map { ($0.ancestors + $0.descendants, collection) }
|
.map { ([$0], collection) }
|
||||||
.flatMap(contentDatabase.insert(statuses:collection:))
|
.flatMap(contentDatabase.insert(statuses:collection:)),
|
||||||
|
networkClient.request(ContextEndpoint.context(id: status.id))
|
||||||
|
.handleEvents(receiveOutput: context.send)
|
||||||
|
.map { ($0.ancestors + $0.descendants, collection) }
|
||||||
|
.flatMap(contentDatabase.insert(statuses:collection:)))
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue