Save / Restore latest seen statuses

This commit is contained in:
Thomas Ricouard 2023-02-04 14:42:10 +01:00
parent b57df4a9d7
commit 288a0eac9f
2 changed files with 26 additions and 1 deletions

View file

@ -41,4 +41,12 @@ actor TimelineCache {
return nil return nil
} }
} }
func setLatestSeenStatuses(ids: [String], for client: Client) {
UserDefaults.standard.set(ids, forKey: client.id)
}
func getLatestSeenStatus(for client: Client) -> [String]? {
UserDefaults.standard.array(forKey: client.id) as? [String]
}
} }

View file

@ -17,6 +17,7 @@ class TimelineViewModel: ObservableObject {
// Internal source of truth for a timeline. // Internal source of truth for a timeline.
private var statuses: [Status] = [] private var statuses: [Status] = []
private var visibileStatusesIds = Set<String>() private var visibileStatusesIds = Set<String>()
var scrollToTopVisible: Bool = false { var scrollToTopVisible: Bool = false {
didSet { didSet {
if scrollToTopVisible { if scrollToTopVisible {
@ -168,9 +169,19 @@ extension TimelineViewModel: StatusesFetcher {
!cachedStatuses.isEmpty, !cachedStatuses.isEmpty,
timeline == .home { timeline == .home {
statuses = cachedStatuses statuses = cachedStatuses
if let latestSeenId = await cache.getLatestSeenStatus(for: client)?.last,
let index = statuses.firstIndex(where: { $0.id == latestSeenId }),
index > 0 {
// Restore cache and scroll to latest seen status.
statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
scrollToIndexAnimated = false
scrollToIndex = index + 1
} else {
// Restore cache and scroll to top.
withAnimation { withAnimation {
statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage) statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
} }
}
// And then we fetch statuses again toget newest statuses from there. // And then we fetch statuses again toget newest statuses from there.
await fetchStatuses() await fetchStatuses()
} else { } else {
@ -311,6 +322,12 @@ extension TimelineViewModel: StatusesFetcher {
func statusDidAppear(status: Status) { func statusDidAppear(status: Status) {
pendingStatusesObserver.removeStatus(status: status) pendingStatusesObserver.removeStatus(status: status)
visibileStatusesIds.insert(status.id) visibileStatusesIds.insert(status.id)
if let client, timeline == .home {
Task {
await cache.setLatestSeenStatuses(ids: visibileStatusesIds.map{ $0 }, for: client)
}
}
} }
func statusDidDisappear(status: Status) { func statusDidDisappear(status: Status) {