import SwiftUI import OrgSocialKit struct DiscoverView: View { @State private var viewModel = DiscoverViewModel() var body: some View { NavigationStack { Group { if viewModel.isLoading && viewModel.users.isEmpty { VStack(spacing: 16) { ProgressView() Text("Loading profiles from relay...") .font(.subheadline) .foregroundStyle(.secondary) } .frame(maxWidth: .infinity, maxHeight: .infinity) } else if let error = viewModel.errorMessage, viewModel.users.isEmpty { ContentUnavailableView { Label("Discover unavailable", systemImage: "person.slash") } description: { Text(error) } actions: { Button("Retry") { Task { await viewModel.load() } } .buttonStyle(.bordered) } } else if viewModel.users.isEmpty { ContentUnavailableView( "No profiles found", systemImage: "person.3", description: Text("No other users registered on this relay.") ) } else { List(viewModel.users) { user in DiscoverUserRow(user: user, viewModel: viewModel) } .listStyle(.plain) .navigationDestination(for: URL.self) { ProfileView(feedURL: $0) } } } .navigationTitle("Discover") .toolbar { ToolbarItem(placement: .navigationBarTrailing) { if viewModel.isLoading { ProgressView() } else { Button { Task { await viewModel.load() } } label: { Image(systemName: "arrow.clockwise") } } } } .task { await viewModel.load() } } } } private struct DiscoverUserRow: View { let user: DiscoverViewModel.DiscoverUser var viewModel: DiscoverViewModel @State private var isToggling = false var body: some View { HStack(spacing: 12) { NavigationLink(value: user.feedURL) { HStack(spacing: 12) { AvatarView(url: user.avatar, nick: user.nick, size: 44) VStack(alignment: .leading, spacing: 3) { if let nick = user.nick { Text("@\(nick)") .font(.subheadline.weight(.semibold)) } if let desc = user.description { Text(desc) .font(.caption) .foregroundStyle(.secondary) .lineLimit(2) } else { Text(user.feedURL.host ?? user.feedURL.absoluteString) .font(.caption) .foregroundStyle(.secondary) .lineLimit(1) } } } } Spacer() if isToggling { ProgressView() .frame(width: 72) } else { Button { isToggling = true Task { if user.isFollowing { await viewModel.unfollow(user: user) } else { await viewModel.follow(user: user) } isToggling = false } } label: { Text(user.isFollowing ? "Unfollow" : "Follow") .font(.subheadline) .fontWeight(user.isFollowing ? .regular : .semibold) .frame(width: 72) } .buttonStyle(.bordered) .tint(user.isFollowing ? .secondary : .accentColor) } } .padding(.vertical, 4) } }