diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+LoadLatestState.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+LoadLatestState.swift index 65ec13d66..1f09b21b0 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+LoadLatestState.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+LoadLatestState.swift @@ -108,6 +108,8 @@ extension HomeTimelineViewModel.LoadLatestState { if newStatuses.isEmpty { viewModel.didLoadLatest.send() } else { + var oldRecords = viewModel.dataController.records + if !latestStatusIDs.isEmpty { viewModel.homeTimelineNavigationBarTitleViewModel.newPostsIncoming() } @@ -115,13 +117,20 @@ extension HomeTimelineViewModel.LoadLatestState { var newRecords: [MastodonFeed] = newStatuses.map { MastodonFeed.fromStatus(.fromEntity($0), kind: .home) } + + if let lastNewId = newRecords.last?.status?.id, let firstOld = oldRecords.first?.status, lastNewId != firstOld.id { + // Add "Load more" + newRecords.append( + MastodonFeed(hasMore: true, isLoadingMore: false, status: firstOld, notification: nil, kind: .none) + ) + } + viewModel.dataController.records = { - var oldRecords = viewModel.dataController.records for (i, record) in newRecords.enumerated() { if let index = oldRecords.firstIndex(where: { $0.status?.reblog?.id == record.id || $0.status?.id == record.id }) { oldRecords[index] = record if newRecords.count > index { - newRecords.remove(at: i) + newRecords.remove(at: index) } } } diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift index d56155d9a..82d4a21ff 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift @@ -150,16 +150,21 @@ extension HomeTimelineViewModel { // fetch data let maxID = status.id - _ = try? await context.apiService.homeTimeline( + let missingStatuses = (try? await context.apiService.homeTimeline( maxID: maxID, authenticationBox: authContext.mastodonAuthenticationBox - ) + ).value) ?? [] record.isLoadingMore = false // reconfigure item again snapshot.reconfigureItems([item]) await updateSnapshotUsingReloadData(snapshot: snapshot) + + let newItems: [MastodonFeed] = missingStatuses.map({ MastodonFeed.fromStatus(.fromEntity($0), kind: .home) }) + var existingItems = Array(dataController.records) + existingItems.removeAll(where: { $0.id == status.id }) // Remove loader item + dataController.records = (newItems + existingItems).removingDuplicates() } } diff --git a/MastodonSDK/Sources/MastodonSDK/MastodonFeed.swift b/MastodonSDK/Sources/MastodonSDK/MastodonFeed.swift index fbeed892f..d3c9c74c5 100644 --- a/MastodonSDK/Sources/MastodonSDK/MastodonFeed.swift +++ b/MastodonSDK/Sources/MastodonSDK/MastodonFeed.swift @@ -20,7 +20,7 @@ public final class MastodonFeed { public let kind: Feed.Kind - init(hasMore: Bool, isLoadingMore: Bool, status: MastodonStatus?, notification: Mastodon.Entity.Notification?, kind: Feed.Kind) { + public init(hasMore: Bool, isLoadingMore: Bool, status: MastodonStatus?, notification: Mastodon.Entity.Notification?, kind: Feed.Kind) { self.id = notification?.id ?? status?.id ?? UUID().uuidString self.hasMore = hasMore self.isLoadingMore = isLoadingMore