import Foundation import Observation import OrgSocialKit @Observable @MainActor final class SearchViewModel { var query = "" var isTagSearch = false var results: [OrgSocialPost] = [] var isLoading = false var errorMessage: String? private let relayClient = RelayClient() private let fetcher = FeedFetcher() var relayURL: URL { let raw = UserDefaults.standard.string(forKey: "relayURL") ?? "https://relay.org-social.org" return URL(string: raw) ?? URL(string: "https://relay.org-social.org")! } func search() async { let trimmed = query.trimmingCharacters(in: .whitespaces) guard !trimmed.isEmpty else { return } isLoading = true errorMessage = nil results = [] defer { isLoading = false } do { let postURLs = try await relayClient.searchPostURLs(query: trimmed, isTag: isTagSearch, from: relayURL) results = try await resolvePosts(from: postURLs) } catch { errorMessage = error.localizedDescription } } private func resolvePosts(from postURLs: [String]) async throws -> [OrgSocialPost] { var byFeed: [String: [String]] = [:] for postURL in postURLs { guard let hashIdx = postURL.lastIndex(of: "#") else { continue } let feedStr = String(postURL[.. $1.date } } }