View Issue Details
| ID | Project | Category | View Status | Date Submitted | Last Update |
|---|---|---|---|---|---|
| 0012150 | Taler | wallet (iOS App) | public | 2026-11-15 19:38 | 2026-11-15 19:38 |
| Reporter | bot-cg [agent] | ||||
| Priority | normal | Severity | minor | ||
| Status | new | ||||
| Summary | 0012150: TalDir contacts can be added and edited but never deleted: wallet-core's deleteContact is not called anywhere (patch attached) | ||||
| Description | A contact, once added -- including one added by mistake or with a typo in the alias -- cannot be removed. Views/TalDir/ContactsView.swift lists the contacts; a row opens AddContactView, whose only button saves. Model/Model+TalDir.swift defines getContacts and addContact and nothing else for contacts. wallet-core has had the operation all along (WalletApiOperation.DeleteContact, request { contact: ContactEntry }); the app has no request struct for it and no control that would use one. Since a contact's identity is its alias, correcting a mistyped alias adds a second entry and the wrong one stays. Patch (contacts-delete.diff): a DeleteContact request and WalletModel.deleteContact(), and a trailing swipe "Delete" on the rows of both sections of the contact list (these are List rows, so the swipe works), followed by a reload. The patch compiles (BUILD SUCCEEDED together with the other patches of this tree); it has NOT been run against a wallet with contacts yet. TalDir is compiled into the GNU_TALER and TALER_NIGHTLY flavours only. | ||||
| Tags | No tags attached. | ||||
| Attached Files | contacts-delete.diff (3,201 bytes)
diff --git a/TalerWallet1/Model/Model+TalDir.swift b/TalerWallet1/Model/Model+TalDir.swift
index 31ec8a24..f86edf0f 100644
--- a/TalerWallet1/Model/Model+TalDir.swift
+++ b/TalerWallet1/Model/Model+TalDir.swift
@@ -66,6 +66,16 @@ fileprivate struct AddContact: WalletBackendFormattedRequest {
func args() -> Args { Args(contact: contact) }
struct Response: Decodable {}
}
+/// A request to delete a contact
+fileprivate struct DeleteContact: WalletBackendFormattedRequest {
+ var contact: ContactEntry
+ var operation: String { "deleteContact" }
+ struct Args: Encodable {
+ var contact: ContactEntry
+ }
+ func args() -> Args { Args(contact: contact) }
+ struct Response: Decodable {}
+}
// MARK: - Contact calls
extension WalletModel {
nonisolated func getContacts(viewHandles: Bool = false)
@@ -85,6 +95,12 @@ extension WalletModel {
// controller.progressToken = request.operation
let _ = try await sendRequest(request, viewHandles: viewHandles)
}
+
+ nonisolated func deleteContact(_ contact: ContactEntry, viewHandles: Bool = false)
+ async throws { // M for MainActor
+ let request = DeleteContact(contact: contact)
+ let _ = try await sendRequest(request, viewHandles: viewHandles)
+ }
}
// MARK: - Alias Types
struct TaldirAliasType: Codable, Hashable {
diff --git a/TalerWallet1/Views/TalDir/ContactsView.swift b/TalerWallet1/Views/TalDir/ContactsView.swift
index 3faac812..7d893912 100644
--- a/TalerWallet1/Views/TalDir/ContactsView.swift
+++ b/TalerWallet1/Views/TalDir/ContactsView.swift
@@ -96,6 +96,22 @@ struct ContactsView: View {
String(localized: "TitleContacts", defaultValue: "Contacts")
}
+ /// wallet-core has had `deleteContact` all along; nothing in the app called it,
+ /// so a contact - including a mistyped one - could never be removed
+ @ViewBuilder func deleteButton(_ contact: ContactEntry) -> some View {
+ Button(role: .destructive) {
+ Task { // runs on MainActor
+ if let _ = try? await model.deleteContact(contact) {
+ await controller.loadContacts(stack.push())
+ }
+ }
+ } label: {
+ Label("Delete", systemImage: "trash")
+ }
+ .tint(WalletColors().negative)
+ .accessibilityIdentifier("button.contact.delete")
+ }
+
var body: some View {
#if PRINT_CHANGES
let _ = Self._printChanges()
@@ -120,6 +136,7 @@ struct ContactsView: View {
contact: contact,
talerURI: talerURI,
subject: subject)
+ .swipeActions(edge: .trailing) { deleteButton(contact) }
}
}
}
@@ -132,6 +149,7 @@ struct ContactsView: View {
contact: contact,
talerURI: talerURI,
subject: subject)
+ .swipeActions(edge: .trailing) { deleteButton(contact) }
}
}
}
| ||||
| child of | 0012147 | new | iOS wallet: state the user can never delete -- audit against the rule that every item must be individually removable [meta] |
| Date Modified | Username | Field | Change |
|---|---|---|---|
| 2026-11-15 19:38 | bot-cg | New Issue | |
| 2026-11-15 19:38 | bot-cg | Relationship added | child of 0012147 |
| 2026-11-15 19:38 | bot-cg | Implementer | => MarcS |
| 2026-11-15 19:38 | bot-cg | Reviewer | => bernaalp |
| 2026-11-15 19:38 | bot-cg | Deployed by | => mikolai |
| 2026-11-15 19:38 | bot-cg | Verifier | => Florian Dold |
| 2026-11-15 19:38 | bot-cg | Communicator | => CM_7 |
| 2026-11-15 19:38 | bot-cg | File Added: contacts-delete.diff |