diff --git a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift index 21999016..2c9562ef 100644 --- a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift +++ b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift @@ -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() @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 { diff --git a/IceCubesApp/App/Tabs/Timeline/AddRemoteTimelineVIew.swift b/IceCubesApp/App/Tabs/Timeline/AddRemoteTimelineVIew.swift index f8ee59e2..5b13ca68 100644 --- a/IceCubesApp/App/Tabs/Timeline/AddRemoteTimelineVIew.swift +++ b/IceCubesApp/App/Tabs/Timeline/AddRemoteTimelineVIew.swift @@ -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() @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() diff --git a/Packages/Explore/Sources/Explore/ExploreView.swift b/Packages/Explore/Sources/Explore/ExploreView.swift index 662eec09..e4b2d525 100644 --- a/Packages/Explore/Sources/Explore/ExploreView.swift +++ b/Packages/Explore/Sources/Explore/ExploreView.swift @@ -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)") diff --git a/Packages/Explore/Sources/Explore/ExploreViewModel.swift b/Packages/Explore/Sources/Explore/ExploreViewModel.swift index 62c7b704..94f5ac42 100644 --- a/Packages/Explore/Sources/Explore/ExploreViewModel.swift +++ b/Packages/Explore/Sources/Explore/ExploreViewModel.swift @@ -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? + private var cancellables = Set() + + 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 } diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index 1532cc82..fbdf71b6 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -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)