import SwiftUI struct ContactsScreen: View { @EnvironmentObject var wrapper: WrapperXMPP @Environment(\.router) var router var body: some View { ZStack { // Background color Color.Material.Background.light .ignoresSafeArea() // Content VStack(spacing: 0) { // Header SharedNavigationBar( centerText: .init(text: L10n.Contacts.title), rightButton: .init( image: Image(systemName: "plus"), action: { router.showScreen(.fullScreenCover) { _ in AddContactOrChannelScreen() } } ) ) // Contacts list if !wrapper.contacts.isEmpty { List { ForEach(wrapper.contacts) { ContactsScreenRow(contact: $0) } } .listStyle(.plain) .background(Color.Material.Background.light) } else { Spacer() } } } } } private struct ContactsScreenRow: View { @EnvironmentObject var wrapper: WrapperXMPP @Environment(\.router) var router var contact: Contact var body: some View { SharedListRow( iconType: .charCircle(contact.name), text: contact.contactJid, controlType: .none ) .onTapGesture { startChat() } .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button { router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) { deleteConfirmation } } label: { Label("", systemImage: "trash") } .tint(Color.red) } .contextMenu { Button(L10n.Contacts.sendMessage, systemImage: "message") { startChat() } Divider() Button(L10n.Contacts.editContact) { print("Edit contact") } Button(L10n.Contacts.selectContact) { print("Select contact") } Divider() Button(L10n.Contacts.deleteContact, systemImage: "trash", role: .destructive) { router.showAlert(.confirmationDialog, title: L10n.Contacts.deleteContact, subtitle: L10n.Contacts.Delete.message) { deleteConfirmation } } } } @ViewBuilder private var deleteConfirmation: some View { Button(role: .destructive) { Task { await deleteCompletely() } } label: { Text(L10n.Contacts.Delete.deleteCompletely) } Button(role: .cancel) {} label: { Text(L10n.Global.cancel) } } private func deleteCompletely() async { router.showModal { LoadingScreen() } defer { router.dismissModal() } do { try await wrapper.deleteContact(contact) } catch { router.showAlert( .alert, title: L10n.Global.Error.title, subtitle: L10n.Contacts.Delete.error ) { Button(L10n.Global.ok, role: .cancel) {} } } } private func startChat() { guard let model = wrapper.chat(with: contact) else { router.showAlert( .alert, title: L10n.Global.Error.title, subtitle: L10n.Conversation.startError ) { Button(L10n.Global.ok, role: .cancel) {} } return } router.showScreen(.push) { _ in ConversationScreen() .navigationBarHidden(true) .environmentObject(model) } } }