Less chatty api calling (#79)
* Limit API calls for instance searching * Limit api calls * Fix empty/initial state * Limit API calls * Delegate empty view logic to viewmodel * When you boosted, display You boosted
This commit is contained in:
parent
a49175fe69
commit
75e9516089
|
@ -6,6 +6,7 @@ import DesignSystem
|
|||
import NukeUI
|
||||
import Shimmer
|
||||
import AppAccount
|
||||
import Combine
|
||||
|
||||
struct AddAccountView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
@ -23,6 +24,8 @@ struct AddAccountView: View {
|
|||
@State private var signInClient: Client?
|
||||
@State private var instances: [InstanceSocial] = []
|
||||
@State private var instanceFetchError: String?
|
||||
|
||||
private let instanceNamePublisher = PassthroughSubject<String, Never>()
|
||||
|
||||
@FocusState private var isInstanceURLFieldFocused: Bool
|
||||
|
||||
|
@ -68,6 +71,9 @@ struct AddAccountView: View {
|
|||
isSigninIn = false
|
||||
}
|
||||
.onChange(of: instanceName) { newValue in
|
||||
instanceNamePublisher.send(newValue)
|
||||
}
|
||||
.onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { newValue in
|
||||
let client = Client(server: newValue)
|
||||
Task {
|
||||
do {
|
||||
|
|
|
@ -5,6 +5,7 @@ import Env
|
|||
import DesignSystem
|
||||
import NukeUI
|
||||
import Shimmer
|
||||
import Combine
|
||||
|
||||
struct AddRemoteTimelineView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
@ -15,6 +16,8 @@ struct AddRemoteTimelineView: View {
|
|||
@State private var instanceName: String = ""
|
||||
@State private var instance: Instance?
|
||||
@State private var instances: [InstanceSocial] = []
|
||||
|
||||
private let instanceNamePublisher = PassthroughSubject<String, Never>()
|
||||
|
||||
@FocusState private var isInstanceURLFieldFocused: Bool
|
||||
|
||||
|
@ -55,12 +58,15 @@ struct AddRemoteTimelineView: View {
|
|||
Button("Cancel", action: { dismiss() })
|
||||
}
|
||||
}
|
||||
.onChange(of: instanceName, perform: { newValue in
|
||||
.onChange(of: instanceName) { newValue in
|
||||
instanceNamePublisher.send(newValue)
|
||||
}
|
||||
.onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { newValue in
|
||||
Task {
|
||||
let client = Client(server: newValue)
|
||||
instance = try? await client.get(endpoint: Instances.instance)
|
||||
}
|
||||
})
|
||||
}
|
||||
.onAppear {
|
||||
isInstanceURLFieldFocused = true
|
||||
let client = InstanceSocialClient()
|
||||
|
|
|
@ -26,10 +26,7 @@ public struct ExploreView: View {
|
|||
}
|
||||
} else if !viewModel.isLoaded {
|
||||
loadingView
|
||||
} else if viewModel.trendingLinks.isEmpty &&
|
||||
viewModel.trendingTags.isEmpty &&
|
||||
viewModel.trendingStatuses.isEmpty &&
|
||||
viewModel.suggestedAccounts.isEmpty {
|
||||
} else if viewModel.allSectionsEmpty {
|
||||
EmptyView(iconName: "magnifyingglass",
|
||||
title: "Search your instance",
|
||||
message: "From this screen you can search anything on \(client.server)")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import SwiftUI
|
||||
import Models
|
||||
import Network
|
||||
import Combine
|
||||
|
||||
@MainActor
|
||||
class ExploreViewModel: ObservableObject {
|
||||
|
@ -37,21 +38,14 @@ class ExploreViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
var allSectionsEmpty: Bool {
|
||||
trendingLinks.isEmpty && trendingTags.isEmpty && trendingStatuses.isEmpty && suggestedAccounts.isEmpty
|
||||
}
|
||||
|
||||
@Published var tokens: [Token] = []
|
||||
@Published var suggestedToken: [Token] = []
|
||||
@Published var searchQuery = "" {
|
||||
didSet {
|
||||
if searchQuery.starts(with: "@") {
|
||||
suggestedToken = [.user, .statuses]
|
||||
} else if searchQuery.starts(with: "#") {
|
||||
suggestedToken = [.tag]
|
||||
} else {
|
||||
suggestedToken = []
|
||||
}
|
||||
search()
|
||||
}
|
||||
}
|
||||
@Published var searchQuery = ""
|
||||
@Published var results: [String: SearchResults] = [:]
|
||||
@Published var isLoaded = false
|
||||
@Published var suggestedAccounts: [Account] = []
|
||||
|
@ -61,6 +55,27 @@ class ExploreViewModel: ObservableObject {
|
|||
@Published var trendingLinks: [Card] = []
|
||||
|
||||
private var searchTask: Task<Void, Never>?
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init() {
|
||||
$searchQuery
|
||||
.removeDuplicates()
|
||||
.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)
|
||||
.sink(receiveValue: { [weak self] newValue in
|
||||
guard let self else { return }
|
||||
|
||||
if self.searchQuery.starts(with: "@") {
|
||||
self.suggestedToken = [.user, .statuses]
|
||||
} else if self.searchQuery.starts(with: "#") {
|
||||
self.suggestedToken = [.tag]
|
||||
} else {
|
||||
self.suggestedToken = []
|
||||
}
|
||||
|
||||
self.search()
|
||||
})
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func fetchTrending() async {
|
||||
guard let client else { return }
|
||||
|
|
|
@ -98,8 +98,12 @@ public struct StatusRowView: View {
|
|||
HStack(spacing: 2) {
|
||||
Image(systemName:"arrow.left.arrow.right.circle.fill")
|
||||
AvatarView(url: viewModel.status.account.avatar, size: .boost)
|
||||
EmojiTextApp(viewModel.status.account.safeDisplayName.asMarkdown, emojis: viewModel.status.account.emojis)
|
||||
Text("boosted")
|
||||
if viewModel.status.account.username != account.account?.username {
|
||||
EmojiTextApp(viewModel.status.account.safeDisplayName.asMarkdown, emojis: viewModel.status.account.emojis)
|
||||
Text("boosted")
|
||||
} else {
|
||||
Text("You boosted")
|
||||
}
|
||||
}
|
||||
.font(.footnote)
|
||||
.foregroundColor(.gray)
|
||||
|
|
Loading…
Reference in New Issue