taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

commit 48c54e435214be9f4dab7484b082f63abd03df4e
parent 23bc0ba4eeea0568c22ad9c87914476a3cca8f24
Author: Marc Stibane <marc@taler.net>
Date:   Sat, 31 Oct 2026 18:10:48 +0100

ContactsView

Diffstat:
ATalerWallet1/Views/TalDir/ContactsView.swift | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 153 insertions(+), 0 deletions(-)

diff --git a/TalerWallet1/Views/TalDir/ContactsView.swift b/TalerWallet1/Views/TalDir/ContactsView.swift @@ -0,0 +1,153 @@ +/* + * This file is part of GNU Taler, ©2022-26 Taler Systems S.A. + * See LICENSE.md + */ +/** + * @author Marc Stibane + */ +import SwiftUI +import taler_swift +import SymLog + +// MARK: - +struct ContactRowView: View { + let stack: CallStack + let contact: ContactEntry + let talerURI: String? + let subject: String? + + @EnvironmentObject private var model: WalletModel + + @State private var showAlert: Bool = false + + private var cancelButton: some View { + Button("Cancel", role: .cancel) { + showAlert = false + } + } + + private var sendNowButton: some View { + Button(contact.petname.isEmpty ? "Send now" : "Send to \(contact.petname)") { + showAlert = false + if let talerURI { + Task { + try? await model.sendTalerUriMailboxMessage(talerURI, +// subjectHint: subject ?? EMPTYSTRING, + to: contact) + dismissTop(stack.push()) + } + } + } + } + + var body: some View { + let label = VStack(alignment: .leading) { + if !contact.petname.isEmpty { + Text(contact.petname) + .talerFont(.title3) + } + Text(contact.alias) + .talerFont(.body) + } + + if let talerURI { // send this to the selected contact + label + .contentShape(.rect) + .frame(maxWidth: .infinity, alignment: .leading) + .background { + Color.primary.opacity(showAlert ? 0.12 : INVISIBLE) + } + .onTapGesture { showAlert.toggle() } + .alert("Send to \(contact.petname)", + isPresented: $showAlert, + actions: { sendNowButton + cancelButton }, + message: { if let subject { + Text(subject) + } }) + + } else { // edit the selected contact + NavigationLink { + let title = String(localized: "TitleEditContact", + defaultValue: "Edit Contact", comment: "View Title, Button") + AddContactView(stack.push(), contact: contact, navTitle: title) + } label: { label } + } + } +} +// MARK: - +/// This view shows the list of contacts +/// called either from TalDir settings (without talerURI), or from CopyShare->TalDirButton (with talerURI) +struct ContactsView: View { + private let symLog = SymLogV(0) + let stack: CallStack + let talerURI: String? + let subject: String? + + @EnvironmentObject private var model: WalletModel + @EnvironmentObject private var controller: Controller + @AppStorage("minimalistic") var minimalistic: Bool = false + @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic + + @State private var contacts: [ContactEntry]? = nil + @State private var showAddDialog: Bool = false + + var navTitle: String { + String(localized: "TitleContacts", defaultValue: "Contacts") + } + + var body: some View { +#if PRINT_CHANGES + let _ = Self._printChanges() + let _ = symLog.vlog() // just to get the # to compare it with .onAppear & onDisappear +#endif + let a11yLabelStr = String(localized: "Add Contact", comment: "a11y for the + button") + let plusButton = PlusButton(accessibilityLabelStr: a11yLabelStr) { + showAddDialog = true + } + let addContactDest = AddContactView(stack.push()) + let actions = Group { + NavLink($showAddDialog) { addContactDest } + } + let contacts = controller.contacts + let ownEntries = contacts.filter({$0.isSelf == true }) + let otherEntries = contacts.filter({$0.isSelf != true }) + List { + if !ownEntries.isEmpty { + Section(header: Text("Own contacts")) { + ForEachWithIndex(array: ownEntries) { index, contact in + ContactRowView(stack: stack.push(), + contact: contact, + talerURI: talerURI, + subject: subject) + } + } + } + Section { + if otherEntries.isEmpty { + Text("No contacts yet...") + } else { + ForEachWithIndex(array: otherEntries) { index, contact in + ContactRowView(stack: stack.push(), + contact: contact, + talerURI: talerURI, + subject: subject) + } + } + } + } + .background(actions) + .listStyle(myListStyle.style).anyView +// .task { await viewDidLoad() } + .refreshable { + controller.hapticNotification(.success) + symLog.log("refreshing") + await controller.loadContacts(stack.push()) + } + .navigationTitle(navTitle) + .navigationBarItems(trailing: plusButton) + .onAppear() { + DebugViewC.shared.setViewID(VIEW_CONTACTS, stack: stack.push()) + } + } // body +}