Timeline: Cleanup

This commit is contained in:
Thomas Ricouard 2023-02-25 19:47:15 +01:00
parent 151154b335
commit 93ee83c65d
2 changed files with 27 additions and 43 deletions

View file

@ -60,7 +60,7 @@ public struct TimelineView: View {
collectionView.isPrefetchingEnabled = true
collectionView.prefetchDataSource = self.prefetcher
}
if viewModel.pendingStatusesEnabled {
if viewModel.timeline.supportNewestPagination {
PendingStatusesObserverView(observer: viewModel.pendingStatusesObserver)
}
}

View file

@ -17,7 +17,7 @@ class TimelineViewModel: ObservableObject {
timeline = oldValue
}
if oldValue != timeline {
await datasource.reset()
await reset()
pendingStatusesObserver.pendingStatuses = []
tag = nil
}
@ -53,7 +53,7 @@ class TimelineViewModel: ObservableObject {
didSet {
if oldValue != client {
Task {
await datasource.reset()
await reset()
}
}
}
@ -67,10 +67,6 @@ class TimelineViewModel: ObservableObject {
}
}
var pendingStatusesEnabled: Bool {
timeline.supportNewestPagination
}
var serverName: String {
client?.server ?? "Error"
}
@ -103,7 +99,6 @@ class TimelineViewModel: ObservableObject {
timeline == .home,
canStreamEvents,
isTimelineVisible,
pendingStatusesEnabled,
await !datasource.contains(statusId: event.status.id)
{
pendingStatusesObserver.pendingStatuses.insert(event.status.id, at: 0)
@ -167,7 +162,7 @@ extension TimelineViewModel: StatusesFetcher {
guard let client else { return }
do {
if await datasource.isEmpty || !timeline.supportNewestPagination {
await datasource.reset()
await reset()
try await fetchFirstPage(client: client)
} else if let latest = await datasource.get().first {
try await fetchNewPagesFrom(latestStatus: latest, client: client)
@ -276,47 +271,36 @@ extension TimelineViewModel: StatusesFetcher {
// Cache statuses for home timeline.
await cacheHome()
// If pending statuses are not enabled, we simply load status on the top regardless of the current position.
if !pendingStatusesEnabled {
pendingStatusesObserver.pendingStatuses = []
// Append new statuses in the timeline indicator.
pendingStatusesObserver.pendingStatuses.insert(contentsOf: newStatuses.map { $0.id }, at: 0)
// High chance the user is scrolled to the top.
// We need to update the statuses state, and then scroll to the previous top most status.
if let topStatusId, visibileStatusesIds.contains(topStatusId), scrollToTopVisible {
pendingStatusesObserver.disableUpdate = true
let statuses = await datasource.get()
statusesState = .display(statuses: statuses,
nextPageState: statuses.count < 20 ? .none : .hasNextPage)
scrollToIndexAnimated = false
scrollToIndex = newStatuses.count + 1
DispatchQueue.main.async {
self.pendingStatusesObserver.disableUpdate = false
self.canStreamEvents = true
}
} else {
// This will keep the scroll position (if the list is scrolled) and prepend statuses on the top.
let statuses = await datasource.get()
withAnimation {
statusesState = .display(statuses: statuses,
nextPageState: statuses.count < 20 ? .none : .hasNextPage)
canStreamEvents = true
}
} else {
// Append new statuses in the timeline indicator.
pendingStatusesObserver.pendingStatuses.insert(contentsOf: newStatuses.map { $0.id }, at: 0)
}
// High chance the user is scrolled to the top.
// We need to update the statuses state, and then scroll to the previous top most status.
if let topStatusId, visibileStatusesIds.contains(topStatusId), scrollToTopVisible {
pendingStatusesObserver.disableUpdate = true
let statuses = await datasource.get()
statusesState = .display(statuses: statuses,
nextPageState: statuses.count < 20 ? .none : .hasNextPage)
scrollToIndexAnimated = false
scrollToIndex = newStatuses.count + 1
DispatchQueue.main.async {
self.pendingStatusesObserver.disableUpdate = false
self.canStreamEvents = true
}
} else {
// This will keep the scroll position (if the list is scrolled) and prepend statuses on the top.
let statuses = await datasource.get()
withAnimation {
statusesState = .display(statuses: statuses,
nextPageState: statuses.count < 20 ? .none : .hasNextPage)
canStreamEvents = true
}
}
// We trigger a new fetch so we can get the next new statuses if any.
// If none, it'll stop there.
if !Task.isCancelled, let latest = await datasource.get().first, let client {
try await fetchNewPagesFrom(latestStatus: latest, client: client)
}
// We trigger a new fetch so we can get the next new statuses if any.
// If none, it'll stop there.
if !Task.isCancelled, let latest = await datasource.get().first, let client {
try await fetchNewPagesFrom(latestStatus: latest, client: client)
}
}