import Foundation import Observation import OrgSocialKit @Observable @MainActor final class DiscoverViewModel { struct DiscoverUser: Identifiable { let feedURL: URL let nick: String? let description: String? let avatar: URL? var id: String { feedURL.absoluteString } var isFollowing: Bool = false } var users: [DiscoverUser] = [] var isLoading = false var errorMessage: String? private var ownFeedURL: URL? { guard let raw = UserDefaults.standard.string(forKey: "publicFeedURL"), let url = URL(string: raw) else { return nil } return url } private var relayURL: URL? { guard let raw = UserDefaults.standard.string(forKey: "relayURL"), let url = URL(string: raw) else { return nil } return url } var useRelay: Bool { UserDefaults.standard.object(forKey: "useRelay") as? Bool ?? true } func load() async { guard useRelay else { errorMessage = "Discover requires a relay. Enable Use Relay in Settings." users = [] return } guard let relay = relayURL else { errorMessage = "No relay URL configured." return } isLoading = true errorMessage = nil defer { isLoading = false } do { let allFeeds = try await RelayClient().fetchFeeds(from: relay) // Refresh the shared follow coordinator so we can mark followed users. await FollowCoordinator.shared.refreshIfNeeded() let coordinator = FollowCoordinator.shared let ownURLString = ownFeedURL?.absoluteString ?? "" // Shuffle and filter out own feed let shuffled = allFeeds.filter { $0.absoluteString != ownURLString }.shuffled() // Fetch profiles in batches of 10 var result: [DiscoverUser] = [] let batchSize = 10 for batchStart in stride(from: 0, to: min(shuffled.count, 100), by: batchSize) { let batch = Array(shuffled[batchStart..