Infintie scrolling
This commit is contained in:
parent
2d040a6313
commit
4b640c76a0
|
@ -18,19 +18,31 @@ struct AccountView: View {
|
||||||
@State private var isFollowing: Bool = false
|
@State private var isFollowing: Bool = false
|
||||||
@State private var accountFollows: Bool = false
|
@State private var accountFollows: Bool = false
|
||||||
|
|
||||||
|
@State private var loadingStatuses: Bool = false
|
||||||
@State private var statuses: [Status]?
|
@State private var statuses: [Status]?
|
||||||
@State private var statusesPinned: [Status]?
|
@State private var statusesPinned: [Status]?
|
||||||
|
@State private var lastSeen: Int?
|
||||||
|
|
||||||
private let animPicCurve = Animation.smooth(duration: 0.25, extraBounce: 0.0)
|
private let animPicCurve = Animation.smooth(duration: 0.25, extraBounce: 0.0)
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if isCurrent {
|
if isCurrent {
|
||||||
|
if accountManager.getClient() != nil {
|
||||||
NavigationStack(path: $navigator.path) {
|
NavigationStack(path: $navigator.path) {
|
||||||
accountView
|
accountView
|
||||||
|
.withSheets(sheetDestination: $navigator.presentedSheet)
|
||||||
.onAppear {
|
.onAppear {
|
||||||
account = accountManager.forceAccount()
|
account = accountManager.forceAccount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ZStack {
|
||||||
|
Color.appBackground
|
||||||
|
|
||||||
|
ProgressView()
|
||||||
|
.progressViewStyle(.circular)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
accountView
|
accountView
|
||||||
}
|
}
|
||||||
|
@ -85,8 +97,10 @@ struct AccountView: View {
|
||||||
account = ref
|
account = ref
|
||||||
|
|
||||||
await updateRelationship()
|
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))
|
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))
|
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()
|
let client = accountManager.getClient()
|
||||||
navigator.presentedSheet = .post(content: "@\(account.username)@\(client?.server ?? "???")")
|
navigator.presentedSheet = .post(content: "@\(account.username)@\(client?.server ?? "???")")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} label: {
|
} label: {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
|
@ -170,7 +182,7 @@ struct AccountView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusesList: some View {
|
var statusesList: some View {
|
||||||
VStack {
|
LazyVStack {
|
||||||
if statuses != nil {
|
if statuses != nil {
|
||||||
if !(statusesPinned?.isEmpty ?? true) {
|
if !(statusesPinned?.isEmpty ?? true) {
|
||||||
ForEach(statusesPinned!, id: \.id) { status in
|
ForEach(statusesPinned!, id: \.id) { status in
|
||||||
|
@ -180,6 +192,9 @@ struct AccountView: View {
|
||||||
if !statuses!.isEmpty {
|
if !statuses!.isEmpty {
|
||||||
ForEach(statuses!, id: \.id) { status in
|
ForEach(statuses!, id: \.id) { status in
|
||||||
CompactPostView(status: status, navigator: navigator)
|
CompactPostView(status: status, navigator: navigator)
|
||||||
|
.onDisappear() {
|
||||||
|
lastSeen = statuses!.firstIndex(where: { $0.id == status.id })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -191,12 +206,26 @@ struct AccountView: View {
|
||||||
if statuses == nil {
|
if statuses == nil {
|
||||||
if let client = accountManager.getClient() {
|
if let client = accountManager.getClient() {
|
||||||
Task {
|
Task {
|
||||||
|
loadingStatuses = true
|
||||||
statuses = try await client.get(endpoint: Accounts.statuses(id: account.id, sinceId: nil, tag: nil, onlyMedia: nil, excludeReplies: nil, pinned: nil))
|
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))
|
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 {
|
func followAccount() async {
|
||||||
|
|
|
@ -11,7 +11,9 @@ struct TimelineView: View {
|
||||||
@State private var timeline: TimelineFilter = .home
|
@State private var timeline: TimelineFilter = .home
|
||||||
@State private var timelines: [TimelineFilter] = [.trending, .home]
|
@State private var timelines: [TimelineFilter] = [.trending, .home]
|
||||||
|
|
||||||
|
@State private var loadingStatuses: Bool = false
|
||||||
@State private var statuses: [Status]?
|
@State private var statuses: [Status]?
|
||||||
|
@State private var lastSeen: Int?
|
||||||
|
|
||||||
@State var timelineModel: FetchTimeline // home timeline by default
|
@State var timelineModel: FetchTimeline // home timeline by default
|
||||||
|
|
||||||
|
@ -54,18 +56,32 @@ struct TimelineView: View {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
ForEach(statuses!, id: \.id) { status in
|
ForEach(statuses!, id: \.id) { status in
|
||||||
VStack(spacing: 2) {
|
LazyVStack(alignment: .leading, spacing: 2) {
|
||||||
CompactPostView(status: status, navigator: navigator)
|
CompactPostView(status: status, navigator: navigator)
|
||||||
|
.onDisappear {
|
||||||
|
guard statuses != nil else { return }
|
||||||
|
lastSeen = statuses!.firstIndex(where: { $0.id == status.id })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.refreshable {
|
.refreshable {
|
||||||
if let client = accountManager.getClient() {
|
if let client = accountManager.getClient() {
|
||||||
Task {
|
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)
|
.padding(.top)
|
||||||
.background(Color.appBackground)
|
.background(Color.appBackground)
|
||||||
.withAppRouter(navigator)
|
.withAppRouter(navigator)
|
||||||
|
@ -91,7 +107,7 @@ struct TimelineView: View {
|
||||||
}
|
}
|
||||||
.scrollDisabled(true)
|
.scrollDisabled(true)
|
||||||
.background(Color.appBackground)
|
.background(Color.appBackground)
|
||||||
.frame(height: 150)
|
.frame(height: 200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,7 +117,7 @@ struct TimelineView: View {
|
||||||
.onAppear {
|
.onAppear {
|
||||||
if let client = accountManager.getClient() {
|
if let client = accountManager.getClient() {
|
||||||
Task {
|
Task {
|
||||||
statuses = try? await client.get(endpoint: Timelines.home(sinceId: nil, maxId: nil, minId: nil))
|
statuses = await timelineModel.fetch(client: client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue