Fix loading of home timeline (IOS-176)
This commit is contained in:
parent
b010b6112e
commit
9ce078ce3e
|
@ -21,7 +21,6 @@ extension HomeTimelineViewController: DataSourceProvider {
|
|||
|
||||
switch item {
|
||||
case .feed(let feed):
|
||||
let managedObjectContext = context.managedObjectContext
|
||||
let item: DataSourceItem? = {
|
||||
guard feed.kind == .home else { return nil }
|
||||
if let status = feed.status {
|
||||
|
|
|
@ -80,7 +80,7 @@ final class HomeTimelineViewModel: NSObject {
|
|||
init(context: AppContext, authContext: AuthContext) {
|
||||
self.context = context
|
||||
self.authContext = authContext
|
||||
self.fetchedResultsController = FeedFetchedResultsController()
|
||||
self.fetchedResultsController = FeedFetchedResultsController(context: context, authContext: authContext)
|
||||
self.homeTimelineNavigationBarTitleViewModel = HomeTimelineNavigationBarTitleViewModel(context: context)
|
||||
super.init()
|
||||
homeTimelineNeedRefresh
|
||||
|
@ -97,6 +97,8 @@ final class HomeTimelineViewModel: NSObject {
|
|||
self.homeTimelineNeedRefresh.send()
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
self.fetchedResultsController.loadInitial(kind: .home)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +112,7 @@ extension HomeTimelineViewModel {
|
|||
|
||||
extension HomeTimelineViewModel {
|
||||
func timelineDidReachEnd() {
|
||||
#warning("Check if required, e.g. when locally caching MastodonStatus")
|
||||
fetchedResultsController.loadNext(kind: .home)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,29 +124,9 @@ extension HomeTimelineViewModel {
|
|||
guard let diffableDataSource = diffableDataSource else { return }
|
||||
var snapshot = diffableDataSource.snapshot()
|
||||
|
||||
|
||||
// let managedObjectContext = context.managedObjectContext
|
||||
// let key = "LoadMore@\(record.objectID)"
|
||||
//
|
||||
// guard let feed = record.object(in: managedObjectContext) else { return }
|
||||
|
||||
guard let status = record.status else { return }
|
||||
record.isLoadingMore = true
|
||||
|
||||
// // keep transient property live
|
||||
// managedObjectContext.cache(feed, key: key)
|
||||
// defer {
|
||||
// managedObjectContext.cache(nil, key: key)
|
||||
// }
|
||||
// do {
|
||||
// // update state
|
||||
// try await managedObjectContext.performChanges {
|
||||
// feed.update(isLoadingMore: true)
|
||||
// }
|
||||
// } catch {
|
||||
// assertionFailure(error.localizedDescription)
|
||||
// }
|
||||
|
||||
|
||||
// reconfigure item
|
||||
snapshot.reconfigureItems([item])
|
||||
await updateSnapshotUsingReloadData(snapshot: snapshot)
|
||||
|
|
|
@ -52,7 +52,7 @@ final class NotificationTimelineViewModel {
|
|||
self.context = context
|
||||
self.authContext = authContext
|
||||
self.scope = scope
|
||||
self.feedFetchedResultsController = FeedFetchedResultsController()
|
||||
self.feedFetchedResultsController = FeedFetchedResultsController(context: context, authContext: authContext)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,44 @@ import MastodonSDK
|
|||
final public class FeedFetchedResultsController {
|
||||
|
||||
@Published public var records: [MastodonFeed] = []
|
||||
|
||||
private let context: AppContext
|
||||
private let authContext: AuthContext
|
||||
|
||||
public init() {}
|
||||
public init(context: AppContext, authContext: AuthContext) {
|
||||
self.context = context
|
||||
self.authContext = authContext
|
||||
}
|
||||
|
||||
public func loadInitial(kind: MastodonFeed.Kind) {
|
||||
Task {
|
||||
records = try await load(kind: kind, sinceId: nil)
|
||||
}
|
||||
}
|
||||
|
||||
public func loadNext(kind: MastodonFeed.Kind) {
|
||||
Task {
|
||||
guard let lastId = records.last?.status?.id else {
|
||||
return loadInitial(kind: kind)
|
||||
}
|
||||
|
||||
records = try await load(kind: kind, sinceId: lastId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension FeedFetchedResultsController {
|
||||
func load(kind: MastodonFeed.Kind, sinceId: MastodonStatus.ID?) async throws -> [MastodonFeed] {
|
||||
switch kind {
|
||||
case .home:
|
||||
return try await context.apiService.homeTimeline(sinceID: sinceId, authenticationBox: authContext.mastodonAuthenticationBox)
|
||||
.value.map { .fromStatus(.fromEntity($0), kind: .home) }
|
||||
case .notificationAll:
|
||||
return try await context.apiService.notifications(maxID: nil, scope: .everything, authenticationBox: authContext.mastodonAuthenticationBox)
|
||||
.value.map { .fromNotification($0, kind: .notificationAll) }
|
||||
case .notificationMentions:
|
||||
return try await context.apiService.notifications(maxID: nil, scope: .mentions, authenticationBox: authContext.mastodonAuthenticationBox)
|
||||
.value.map { .fromNotification($0, kind: .notificationMentions) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import MastodonSDK
|
|||
|
||||
public final class StatusFetchedResultsController {
|
||||
@MainActor
|
||||
@Published public private(set) var records: [MastodonStatus] = []
|
||||
@Published
|
||||
public private(set) var records: [MastodonStatus] = []
|
||||
|
||||
@MainActor
|
||||
public init(records: [MastodonStatus] = []) {
|
||||
|
|
|
@ -4,6 +4,14 @@ import Foundation
|
|||
import CoreDataStack
|
||||
|
||||
public final class MastodonFeed {
|
||||
|
||||
public enum Kind {
|
||||
case home
|
||||
case notificationAll
|
||||
case notificationMentions
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public var hasMore: Bool = false
|
||||
public var isLoadingMore: Bool = false
|
||||
|
||||
|
@ -13,6 +21,7 @@ public final class MastodonFeed {
|
|||
public let kind: Feed.Kind
|
||||
|
||||
init(hasMore: Bool, isLoadingMore: Bool, status: MastodonStatus?, notification: Mastodon.Entity.Notification?, kind: Feed.Kind) {
|
||||
self.id = status?.id ?? notification?.id ?? UUID().uuidString
|
||||
self.hasMore = hasMore
|
||||
self.isLoadingMore = isLoadingMore
|
||||
self.status = status
|
||||
|
@ -45,10 +54,11 @@ public extension MastodonFeed {
|
|||
|
||||
extension MastodonFeed: Hashable {
|
||||
public static func == (lhs: MastodonFeed, rhs: MastodonFeed) -> Bool {
|
||||
lhs.status?.id == rhs.status?.id || lhs.notification?.id == rhs.notification?.id
|
||||
lhs.id == rhs.id && (lhs.status?.id == rhs.status?.id || lhs.notification?.id == rhs.notification?.id)
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(id)
|
||||
hasher.combine(status)
|
||||
hasher.combine(notification)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue