Timeline: cleanup datasource near bottom

This commit is contained in:
Thomas Ricouard 2024-09-15 13:25:51 +02:00
parent 0b7c6a799f
commit 93421c56d9
3 changed files with 29 additions and 11 deletions

View file

@ -65,7 +65,7 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
}
.padding(.horizontal, .layoutPadding)
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
.listRowBackground(theme.primaryBackgroundColor)
#endif
case .none:

View file

@ -57,7 +57,7 @@ import SwiftUI
}
@ObservationIgnored
private var visibileStatuses: [Status] = []
private var visibleStatuses: [Status] = []
private var canStreamEvents: Bool = true {
didSet {
@ -301,6 +301,9 @@ extension TimelineViewModel: StatusesFetcher {
private func updateTimelineWithNewStatuses(_ newStatuses: [Status]) async {
let topStatus = await datasource.getFiltered().first
await datasource.insert(contentOf: newStatuses, at: 0)
if let lastVisible = visibleStatuses.last {
await datasource.remove(after: lastVisible, safeOffset: 15)
}
await cache()
pendingStatusesObserver.pendingStatuses.insert(contentsOf: newStatuses.map(\.id), at: 0)
@ -308,7 +311,7 @@ extension TimelineViewModel: StatusesFetcher {
let nextPageState: StatusesState.PagingState = statuses.count < 20 ? .none : .hasNextPage
if let topStatus = topStatus,
visibileStatuses.contains(where: { $0.id == topStatus.id }),
visibleStatuses.contains(where: { $0.id == topStatus.id }),
scrollToTopVisible
{
updateTimelineWithScrollToTop(newStatuses: newStatuses, statuses: statuses, nextPageState: nextPageState)
@ -359,17 +362,17 @@ extension TimelineViewModel: StatusesFetcher {
func statusDidAppear(status: Status) {
pendingStatusesObserver.removeStatus(status: status)
visibileStatuses.insert(status, at: 0)
visibleStatuses.insert(status, at: 0)
if let client, timeline.supportNewestPagination {
Task {
await cache.setLatestSeenStatuses(visibileStatuses, for: client, filter: timeline.id)
await cache.setLatestSeenStatuses(visibleStatuses, for: client, filter: timeline.id)
}
}
}
func statusDidDisappear(status: Status) {
visibileStatuses.removeAll(where: { $0.id == status.id })
visibleStatuses.removeAll(where: { $0.id == status.id })
}
}
@ -419,9 +422,10 @@ extension TimelineViewModel {
}
private func handleDeleteEvent(_ event: StreamEventDelete) async {
await datasource.remove(event.status)
await cache()
await updateStatusesState()
if let _ = await datasource.remove(event.status) {
await cache()
await updateStatusesState()
}
}
private func handleStatusUpdateEvent(_ event: StreamEventStatusUpdate, client: Client) async {

View file

@ -67,12 +67,26 @@ actor TimelineDatasource {
func insert(contentOf: [Status], at: Int) {
statuses.insert(contentsOf: contentOf, at: at)
}
func remove(after: Status, safeOffset: Int) {
if let index = statuses.firstIndex(of: after) {
let safeIndex = index + safeOffset
if statuses.count > safeIndex {
statuses.removeSubrange(safeIndex..<statuses.endIndex)
}
}
}
func replace(_ status: Status, at: Int) {
statuses[at] = status
}
func remove(_ statusId: String) {
statuses.removeAll(where: { $0.id == statusId })
func remove(_ statusId: String) -> Status? {
if let index = statuses.firstIndex(where: { status in
status.id == statusId
}) {
return statuses.remove(at: index)
}
return nil
}
}