import SwiftUI import OrgSocialKit struct GroupsView: View { @State private var viewModel = GroupsViewModel() var body: some View { NavigationStack { Group { if viewModel.isLoadingGroups { ProgressView() .frame(maxWidth: .infinity, maxHeight: .infinity) } else if let error = viewModel.groupsError { ContentUnavailableView { Label("Groups unavailable", systemImage: "person.3.slash") } description: { Text(error) } actions: { Button("Retry") { Task { await viewModel.loadGroups() } } .buttonStyle(.bordered) } } else if viewModel.groups.isEmpty { ContentUnavailableView( "No groups", systemImage: "person.3", description: Text("No groups are registered on this relay.") ) } else { List(viewModel.groups) { group in NavigationLink(value: group) { Label(group.name, systemImage: "person.3.fill") } } } } .navigationTitle("Groups") .task { await viewModel.loadGroups() } .navigationDestination(for: GroupsViewModel.GroupItem.self) { group in GroupPostsView(group: group, viewModel: viewModel) } } } } private struct GroupPostsView: View { let group: GroupsViewModel.GroupItem var viewModel: GroupsViewModel @State private var showCompose = false var body: some View { Group { if viewModel.isLoadingPosts { ProgressView() .frame(maxWidth: .infinity, maxHeight: .infinity) } else if let error = viewModel.postsError { ContentUnavailableView { Label("Could not load posts", systemImage: "exclamationmark.triangle") } description: { Text(error) } actions: { Button("Retry") { Task { await viewModel.loadPosts(for: group) } } .buttonStyle(.bordered) } } else if viewModel.posts.isEmpty { ContentUnavailableView( "No posts", systemImage: "bubble.left.and.bubble.right", description: Text("This group has no posts yet.") ) } else { List { ForEach(viewModel.posts, id: \.timestamp) { post in PostRowView(post: post) .listRowSeparator(.visible) .listRowSeparatorTint(Color.secondary.opacity(0.2)) .listRowInsets(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)) .listRowBackground(Color.clear) } } .listStyle(.plain) .navigationDestination(for: URL.self) { ProfileView(feedURL: $0) } .navigationDestination(for: ThreadRoute.self) { ThreadView(postURL: $0.postURL, relayURL: $0.relayURL) } } } .navigationTitle(group.name) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { showCompose = true } label: { Image(systemName: "square.and.pencil") } } } .sheet(isPresented: $showCompose) { let relayBase = UserDefaults.standard.string(forKey: "relayURL") ?? "https://relay.org-social.org" ComposeView(group: "\(group.name) \(relayBase)") } .task { await viewModel.loadPosts(for: group) } } }