ContactsView.swift (5428B)
1 /* 2 * This file is part of GNU Taler, ©2022-26 Taler Systems S.A. 3 * See LICENSE.md 4 */ 5 /** 6 * @author Marc Stibane 7 */ 8 import SwiftUI 9 import taler_swift 10 import SymLog 11 12 // MARK: - 13 struct ContactRowView: View { 14 let stack: CallStack 15 let contact: ContactEntry 16 let talerURI: String? 17 let subject: String? 18 19 @EnvironmentObject private var model: WalletModel 20 21 @State private var showAlert: Bool = false 22 23 private var cancelButton: some View { 24 Button("Cancel", role: .cancel) { 25 showAlert = false 26 } 27 } 28 29 private var sendNowButton: some View { 30 Button(contact.petname.isEmpty ? "Send now" : "Send to \(contact.petname)") { 31 showAlert = false 32 if let talerURI { 33 Task { 34 try? await model.sendTalerUriMailboxMessage(talerURI, 35 // subjectHint: subject ?? EMPTYSTRING, 36 to: contact) 37 dismissTop(stack.push()) 38 } 39 } 40 } 41 } 42 43 var body: some View { 44 let label = VStack(alignment: .leading) { 45 if !contact.petname.isEmpty { 46 Text(contact.petname) 47 .talerFont(.title3) 48 } 49 Text(contact.alias) 50 .talerFont(.body) 51 } 52 53 if let talerURI { // send this to the selected contact 54 label 55 .contentShape(.rect) 56 .frame(maxWidth: .infinity, alignment: .leading) 57 .background { 58 Color.primary.opacity(showAlert ? 0.12 : INVISIBLE) 59 } 60 .onTapGesture { showAlert.toggle() } 61 .alert("Send to \(contact.petname)", 62 isPresented: $showAlert, 63 actions: { sendNowButton 64 cancelButton }, 65 message: { if let subject { 66 Text(subject) 67 } }) 68 69 } else { // edit the selected contact 70 NavigationLink { 71 let title = String(localized: "TitleEditContact", 72 defaultValue: "Edit Contact", comment: "View Title, Button") 73 AddContactView(stack.push(), contact: contact, navTitle: title) 74 } label: { label } 75 } 76 } 77 } 78 // MARK: - 79 /// This view shows the list of contacts 80 /// called either from TalDir settings (without talerURI), or from CopyShare->TalDirButton (with talerURI) 81 struct ContactsView: View { 82 private let symLog = SymLogV(0) 83 let stack: CallStack 84 let talerURI: String? 85 let subject: String? 86 87 @EnvironmentObject private var model: WalletModel 88 @EnvironmentObject private var controller: Controller 89 @AppStorage("minimalistic") var minimalistic: Bool = false 90 @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic 91 92 @State private var contacts: [ContactEntry]? = nil 93 @State private var showAddDialog: Bool = false 94 95 var navTitle: String { 96 String(localized: "TitleContacts", defaultValue: "Contacts") 97 } 98 99 var body: some View { 100 #if PRINT_CHANGES 101 let _ = Self._printChanges() 102 let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear 103 #endif 104 let a11yLabelStr = String(localized: "Add contact", comment: "a11y for the + button") 105 let plusButton = PlusButton(accessibilityLabelStr: a11yLabelStr) { 106 showAddDialog = true 107 } 108 let addContactDest = AddContactView(stack.push()) 109 let actions = Group { 110 NavLink($showAddDialog) { addContactDest } 111 } 112 let contacts = controller.contacts 113 let ownEntries = contacts.filter({$0.isSelf == true }) 114 let otherEntries = contacts.filter({$0.isSelf != true }) 115 List { 116 if !ownEntries.isEmpty { 117 Section(header: Text("Own contacts")) { 118 ForEachWithIndex(array: ownEntries) { index, contact in 119 ContactRowView(stack: stack.push(), 120 contact: contact, 121 talerURI: talerURI, 122 subject: subject) 123 } 124 } 125 } 126 Section { 127 if otherEntries.isEmpty { 128 Text("No contacts yet...") 129 } else { 130 ForEachWithIndex(array: otherEntries) { index, contact in 131 ContactRowView(stack: stack.push(), 132 contact: contact, 133 talerURI: talerURI, 134 subject: subject) 135 } 136 } 137 } 138 } 139 .background(actions) 140 .listStyle(myListStyle.style).anyView 141 // .task { await viewDidLoad() } 142 .refreshable { 143 controller.hapticNotification(.success) 144 symLog.log("refreshing") 145 await controller.loadContacts(stack.push()) 146 } 147 .navigationTitle(navTitle) 148 .navigationBarItems(trailing: plusButton) 149 .onAppear() { 150 DebugViewC.shared.setViewID(VIEW_CONTACTS, stack: stack.push()) 151 } 152 } // body 153 }