Paginate search results fix #2143

This commit is contained in:
Thomas Ricouard 2024-07-31 11:19:43 +02:00
parent 719c023369
commit 123f05538a
9 changed files with 74 additions and 13 deletions

View file

@ -150,7 +150,7 @@ public enum AccountsListMode {
state = .loading
try await Task.sleep(for: .milliseconds(250))
var results: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery,
type: "accounts",
type: .accounts,
offset: nil,
following: true),
forceVersion: .v2)

View file

@ -260,7 +260,7 @@ public enum SettingsStartingPoint {
public func navigateToAccountFrom(acct: String, url: URL) async {
guard let client else { return }
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: acct,
type: "accounts",
type: .accounts,
offset: nil,
following: nil),
forceVersion: .v2)
@ -274,7 +274,7 @@ public enum SettingsStartingPoint {
public func navigateToAccountFrom(url: URL) async {
guard let client else { return }
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: url.absoluteString,
type: "accounts",
type: .accounts,
offset: nil,
following: nil),
forceVersion: .v2)

View file

@ -181,6 +181,9 @@ public struct ExploreView: View {
#endif
}
}
if viewModel.searchScope == .people {
makeNextPageView(for: .accounts)
}
}
}
if !results.hashtags.isEmpty, viewModel.searchScope == .all || viewModel.searchScope == .hashtags {
@ -196,6 +199,9 @@ public struct ExploreView: View {
#endif
.padding(.vertical, 4)
}
if viewModel.searchScope == .hashtags {
makeNextPageView(for: .hashtags)
}
}
}
if !results.statuses.isEmpty, viewModel.searchScope == .all || viewModel.searchScope == .posts {
@ -211,6 +217,9 @@ public struct ExploreView: View {
#endif
.padding(.vertical, 8)
}
if viewModel.searchScope == .posts {
makeNextPageView(for: .statuses)
}
}
}
}
@ -345,4 +354,14 @@ public struct ExploreView: View {
viewModel.scrollToTopVisible = false
}
}
private func makeNextPageView(for type: Search.EntityType) -> some View {
NextPageView {
await viewModel.fetchNextPage(of: type)
}
.padding(.horizontal, .layoutPadding)
#if !os(visionOS)
.listRowBackground(theme.primaryBackgroundColor)
#endif
}
}

View file

@ -115,4 +115,42 @@ import SwiftUI
isSearching = false
}
}
func fetchNextPage(of type: Search.EntityType) async {
guard let client, !searchQuery.isEmpty,
let results = results[searchQuery] else { return }
do {
let offset = switch type {
case .accounts:
results.accounts.count
case .hashtags:
results.hashtags.count
case .statuses:
results.statuses.count
}
var newPageResults: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery,
type: type,
offset: offset,
following: nil),
forceVersion: .v2)
if type == .accounts {
let relationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: newPageResults.accounts.map(\.id)))
newPageResults.relationships = relationships
}
switch type {
case .accounts:
self.results[searchQuery]?.accounts.append(contentsOf: newPageResults.accounts)
self.results[searchQuery]?.relationships.append(contentsOf: newPageResults.relationships)
case .hashtags:
self.results[searchQuery]?.hashtags.append(contentsOf: newPageResults.hashtags)
case .statuses:
self.results[searchQuery]?.statuses.append(contentsOf: newPageResults.statuses)
}
} catch {
}
}
}

View file

@ -5,10 +5,10 @@ public struct SearchResults: Decodable {
case accounts, statuses, hashtags
}
public let accounts: [Account]
public var accounts: [Account]
public var relationships: [Relationship] = []
public let statuses: [Status]
public let hashtags: [Tag]
public var statuses: [Status]
public var hashtags: [Tag]
public var isEmpty: Bool {
accounts.isEmpty && statuses.isEmpty && hashtags.isEmpty

View file

@ -1,8 +1,12 @@
import Foundation
public enum Search: Endpoint {
case search(query: String, type: String?, offset: Int?, following: Bool?)
case accountsSearch(query: String, type: String?, offset: Int?, following: Bool?)
public enum EntityType: String, Sendable {
case accounts, hashtags, statuses
}
case search(query: String, type: EntityType?, offset: Int?, following: Bool?)
case accountsSearch(query: String, type: EntityType?, offset: Int?, following: Bool?)
public func path() -> String {
switch self {
@ -19,7 +23,7 @@ public enum Search: Endpoint {
let .accountsSearch(query, type, offset, following):
var params: [URLQueryItem] = [.init(name: "q", value: query)]
if let type {
params.append(.init(name: "type", value: type))
params.append(.init(name: "type", value: type.rawValue))
}
if let offset {
params.append(.init(name: "offset", value: String(offset)))

View file

@ -58,7 +58,7 @@ import SwiftUI
private func fetchRemoteStatus() async -> Bool {
guard let client, let remoteStatusURL else { return false }
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: remoteStatusURL.absoluteString,
type: "statuses",
type: .statuses,
offset: nil,
following: nil),
forceVersion: .v2)

View file

@ -591,7 +591,7 @@ public extension StatusEditor {
showRecentsTagsInline = false
query.removeFirst()
results = try await client.get(endpoint: Search.search(query: query,
type: "hashtags",
type: .hashtags,
offset: 0,
following: nil),
forceVersion: .v2)

View file

@ -280,7 +280,7 @@ import SwiftUI
embed = try await client.get(endpoint: Statuses.status(id: String(id)))
} else {
let results: SearchResults = try await client.get(endpoint: Search.search(query: url.absoluteString,
type: "statuses",
type: .statuses,
offset: 0,
following: nil),
forceVersion: .v2)
@ -449,7 +449,7 @@ import SwiftUI
guard isRemote, let remoteStatusURL = URL(string: finalStatus.url ?? "") else { return false }
isLoadingRemoteContent = true
let results: SearchResults? = try? await client.get(endpoint: Search.search(query: remoteStatusURL.absoluteString,
type: "statuses",
type: .statuses,
offset: nil,
following: nil),
forceVersion: .v2)