Infintie scrolling

This commit is contained in:
Lumaa 2024-01-06 02:50:54 +01:00
parent 2d040a6313
commit 4b640c76a0
2 changed files with 57 additions and 12 deletions

View File

@ -18,18 +18,30 @@ struct AccountView: View {
@State private var isFollowing: Bool = false
@State private var accountFollows: Bool = false
@State private var loadingStatuses: Bool = false
@State private var statuses: [Status]?
@State private var statusesPinned: [Status]?
@State private var lastSeen: Int?
private let animPicCurve = Animation.smooth(duration: 0.25, extraBounce: 0.0)
var body: some View {
if isCurrent {
NavigationStack(path: $navigator.path) {
accountView
.onAppear {
account = accountManager.forceAccount()
}
if accountManager.getClient() != nil {
NavigationStack(path: $navigator.path) {
accountView
.withSheets(sheetDestination: $navigator.presentedSheet)
.onAppear {
account = accountManager.forceAccount()
}
}
} else {
ZStack {
Color.appBackground
ProgressView()
.progressViewStyle(.circular)
}
}
} else {
accountView
@ -85,8 +97,10 @@ struct AccountView: View {
account = ref
await updateRelationship()
loadingStatuses = true
statuses = try? await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: nil, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: nil))
statusesPinned = try? await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: nil, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: true))
loadingStatuses = false
}
}
}
@ -138,8 +152,6 @@ struct AccountView: View {
let client = accountManager.getClient()
navigator.presentedSheet = .post(content: "@\(account.username)@\(client?.server ?? "???")")
}
} label: {
HStack {
Spacer()
@ -170,7 +182,7 @@ struct AccountView: View {
}
var statusesList: some View {
VStack {
LazyVStack {
if statuses != nil {
if !(statusesPinned?.isEmpty ?? true) {
ForEach(statusesPinned!, id: \.id) { status in
@ -180,6 +192,9 @@ struct AccountView: View {
if !statuses!.isEmpty {
ForEach(statuses!, id: \.id) { status in
CompactPostView(status: status, navigator: navigator)
.onDisappear() {
lastSeen = statuses!.firstIndex(where: { $0.id == status.id })
}
}
}
} else {
@ -191,12 +206,26 @@ struct AccountView: View {
if statuses == nil {
if let client = accountManager.getClient() {
Task {
loadingStatuses = true
statuses = try await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: nil, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: nil))
statusesPinned = try await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: nil, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: true))
loadingStatuses = false
}
}
}
}
.onChange(of: lastSeen ?? 0) { _, new in
guard statuses != nil && new >= statuses!.count - 6 && !loadingStatuses else { return }
if let client = accountManager.getClient(), let lastStatus = statuses!.last {
Task {
loadingStatuses = true
if let newStatuses: [Status] = try await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: lastStatus.id, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: nil)) {
statuses?.append(contentsOf: newStatuses)
}
loadingStatuses = false
}
}
}
}
func followAccount() async {

View File

@ -11,7 +11,9 @@ struct TimelineView: View {
@State private var timeline: TimelineFilter = .home
@State private var timelines: [TimelineFilter] = [.trending, .home]
@State private var loadingStatuses: Bool = false
@State private var statuses: [Status]?
@State private var lastSeen: Int?
@State var timelineModel: FetchTimeline // home timeline by default
@ -54,18 +56,32 @@ struct TimelineView: View {
// }
ForEach(statuses!, id: \.id) { status in
VStack(spacing: 2) {
LazyVStack(alignment: .leading, spacing: 2) {
CompactPostView(status: status, navigator: navigator)
.onDisappear {
guard statuses != nil else { return }
lastSeen = statuses!.firstIndex(where: { $0.id == status.id })
}
}
}
}
.refreshable {
if let client = accountManager.getClient() {
Task {
statuses = try? await client.get(endpoint: Timelines.home(sinceId: nil, maxId: nil, minId: nil))
loadingStatuses = true
statuses = await timelineModel.fetch(client: client)
loadingStatuses = false
}
}
}
.onChange(of: lastSeen ?? 0) { _, new in
guard !loadingStatuses else { return }
Task {
loadingStatuses = true
statuses = await timelineModel.addStatuses(lastStatusIndex: new)
loadingStatuses = false
}
}
.padding(.top)
.background(Color.appBackground)
.withAppRouter(navigator)
@ -91,7 +107,7 @@ struct TimelineView: View {
}
.scrollDisabled(true)
.background(Color.appBackground)
.frame(height: 150)
.frame(height: 200)
}
}
} else {
@ -101,7 +117,7 @@ struct TimelineView: View {
.onAppear {
if let client = accountManager.getClient() {
Task {
statuses = try? await client.get(endpoint: Timelines.home(sinceId: nil, maxId: nil, minId: nil))
statuses = await timelineModel.fetch(client: client)
}
}
}