Smarter timeline

This commit is contained in:
Thomas Ricouard 2023-01-05 06:39:23 +01:00
parent dcdd8402e9
commit 511717e492
2 changed files with 21 additions and 17 deletions

View file

@ -27,6 +27,7 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
case let .display(statuses, nextPageState): case let .display(statuses, nextPageState):
ForEach(statuses, id: \.viewId) { status in ForEach(statuses, id: \.viewId) { status in
StatusRowView(viewModel: .init(status: status, isCompact: false)) StatusRowView(viewModel: .init(status: status, isCompact: false))
.id(status.id)
.padding(.horizontal, .layoutPadding) .padding(.horizontal, .layoutPadding)
Divider() Divider()
.padding(.vertical, .dividerPadding) .padding(.vertical, .dividerPadding)

View file

@ -47,10 +47,8 @@ class TimelineViewModel: ObservableObject, StatusesFetcher {
var pendingStatusesButtonTitle: String { var pendingStatusesButtonTitle: String {
switch pendingStatusesState { switch pendingStatusesState {
case .stream: case .stream, .refresh:
return "\(pendingStatuses.count) new posts" return "\(pendingStatuses.count) new posts"
case .refresh:
return "See new posts"
} }
} }
@ -77,11 +75,12 @@ class TimelineViewModel: ObservableObject, StatusesFetcher {
minId: nil, minId: nil,
offset: statuses.count)) offset: statuses.count))
statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage) statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
} else if let first = statuses.first { } else if let first = pendingStatuses.first ?? statuses.first {
var newStatuses: [Status] = await fetchNewPages(minId: first.id, maxPages: 10) var newStatuses: [Status] = await fetchNewPages(minId: first.id, maxPages: 20)
if userIntent || !pendingStatusesEnabled { if userIntent || !pendingStatusesEnabled {
pendingStatuses.insert(contentsOf: newStatuses, at: 0)
statuses.insert(contentsOf: pendingStatuses, at: 0)
pendingStatuses = [] pendingStatuses = []
statuses.insert(contentsOf: newStatuses, at: 0)
withAnimation { withAnimation {
statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage) statusesState = .display(statuses: statuses, nextPageState: statuses.count < 20 ? .none : .hasNextPage)
} }
@ -116,7 +115,7 @@ class TimelineViewModel: ObservableObject, StatusesFetcher {
latestMinId = newStatuses.first?.id ?? "" latestMinId = newStatuses.first?.id ?? ""
} }
} catch { } catch {
return [] return allStatuses
} }
return allStatuses return allStatuses
} }
@ -145,20 +144,24 @@ class TimelineViewModel: ObservableObject, StatusesFetcher {
} }
func handleEvent(event: any StreamEvent, currentAccount: CurrentAccount) { func handleEvent(event: any StreamEvent, currentAccount: CurrentAccount) {
if let event = event as? StreamEventUpdate { if let event = event as? StreamEventUpdate,
if event.status.account.id == currentAccount.account?.id, pendingStatusesEnabled,
timeline == .home { !statuses.contains(where: { $0.id == event.status.id }),
statuses.insert(event.status, at: 0) !pendingStatuses.contains(where: { $0.id == event.status.id }){
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage) if event.status.account.id == currentAccount.account?.id, pendingStatuses.isEmpty {
} else if pendingStatusesEnabled, withAnimation {
!statuses.contains(where: { $0.id == event.status.id }), statuses.insert(event.status, at: 0)
!pendingStatuses.contains(where: { $0.id == event.status.id }){ statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
}
} else {
pendingStatuses.insert(event.status, at: 0) pendingStatuses.insert(event.status, at: 0)
pendingStatusesState = .stream pendingStatusesState = .stream
} }
} else if let event = event as? StreamEventDelete { } else if let event = event as? StreamEventDelete {
statuses.removeAll(where: { $0.id == event.status }) withAnimation {
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage) statuses.removeAll(where: { $0.id == event.status })
statusesState = .display(statuses: statuses, nextPageState: .hasNextPage)
}
} else if let event = event as? StreamEventStatusUpdate { } else if let event = event as? StreamEventStatusUpdate {
if let originalIndex = statuses.firstIndex(where: { $0.id == event.status.id }) { if let originalIndex = statuses.firstIndex(where: { $0.id == event.status.id }) {
statuses[originalIndex] = event.status statuses[originalIndex] = event.status