View Issue Details

IDProjectCategoryView StatusLast Update
0012106Talerwallet (iOS App)public2026-11-11 02:05
Reporterbot-cg [agent] Assigned ToResolution deadline
ImplementerReviewer 
Release signed byDeployed by 
VerifierCommunicatorCM_7  
Data protection authority notification requiredNo  
CSIRT notification requiredNo  
Estimated effort (hours)Actual effort (hours)0 
Fast-trackNo
Work packagenone
PrioritynormalSeverityminorReproducibilityhave not tried
Status newResolutionopen 
Summary0012106: iOS: taler://add-exchange link hangs on "Scanning..." for ever (ExchangeListView clears URLSheet's URL binding)
DescriptionOpening a taler://add-exchange/... link leaves the iOS app on the "Loading… / Scanning..." sheet for ever; the exchange is never offered for adding.

What the user sees for taler://add-exchange/tripwire.taler.net:8445/ on a fresh wallet:
- iOS: "Loading…", spinner, "Scanning...", Cancel; stays there (before-ios-1.png, still the same after 30 s).
- WebExtension: "Add exchange / Add https://tripwire.taler.net:8445/ as a wallet exchange." with Continue (before-web-1.png), then the exchange's detail page (before-web-2.png).
- Android rejects the URI as unsupported (0011621).

Cause (origin/master 674b7915): TalerWallet1/Views/Sheets/URLSheet.swift:56-57 shows ExchangeListView(url: $passedURL) for .addExchange. ExchangeListView's .task (Views/Settings/Exchange/ExchangeListView.swift:76-84) copies the URL into the add alert and then sets url = nil, which clears URLSheet's own passedURL. URLSheet's body (`if let urlCommand, let passedURL`) then falls back to its LoadingView "Scanning..." branch, whose passUrlOnce() has nothing left to pass (urlToOpen was cleared too), so the sheet never recovers. URL parsing itself is fine (Controller.swift command(): "add-exchange" -> .addExchange).

Patch (ios-add-exchange-uri-scanning.patch): URLSheet keeps a separate @State exchangeURL for ExchangeListView to consume, so passedURL stays set. Verified with a GNU_Taler Release simulator build: the same link opens Payment Services with the "Add payment service" alert prefilled with the URI (after-ios-1.png); "Add" adds the exchange (after-ios-2.png, "tripwire.taler.net / Status: Ready").

(0011621 notes that add-exchange was said to be fixed on iOS; on current master it hangs as described.)

Assisted by LLM
Steps To ReproduceOpen taler://add-exchange/tripwire.taler.net:8445/ (e.g. from Safari or `xcrun simctl openurl`) in the app.
TagsNo tags attached.
Attached Files
before-ios-1.png (126,695 bytes)   
before-ios-1.png (126,695 bytes)   
before-web-1.png (59,128 bytes)   
before-web-1.png (59,128 bytes)   
before-web-2.png (108,884 bytes)   
before-web-2.png (108,884 bytes)   
after-ios-1.png (353,822 bytes)
after-ios-2.png (249,100 bytes)   
after-ios-2.png (249,100 bytes)   
ios-add-exchange-uri-scanning.patch (1,590 bytes)   
diff --git a/TalerWallet1/Views/Sheets/URLSheet.swift b/TalerWallet1/Views/Sheets/URLSheet.swift
index 634207ec..91c97cba 100644
--- a/TalerWallet1/Views/Sheets/URLSheet.swift
+++ b/TalerWallet1/Views/Sheets/URLSheet.swift
@@ -25,6 +25,7 @@ struct URLSheet: View {
     @State private var summary = EMPTYSTRING
     @State private var urlCommand: UrlCommand?
     @State private var passedURL: URL?
+    @State private var exchangeURL: URL?        // consumed (set to nil) by ExchangeListView
 
     init(_ stack: CallStack, selectedBalance: Balance? = nil,
                                    urlToOpen: Binding<URL?>? = nil,
@@ -44,6 +45,7 @@ struct URLSheet: View {
         } else if let sheetURL {
             (urlCommand, passedURL) = controller.urlCommand(sheetURL, stack: stack.push())
         }
+        exchangeURL = passedURL
     }
 
     var body: some View {
@@ -54,7 +56,9 @@ struct URLSheet: View {
             if let urlCommand, let passedURL {
                 switch urlCommand {
                     case .addExchange:      // TODO: just check the ToS
-                        ExchangeListView(stack: stack.push(), url: $passedURL)
+                        // not $passedURL: ExchangeListView clears its binding once it has read the URL,
+                        // which would drop this sheet back to "Scanning..." for ever
+                        ExchangeListView(stack: stack.push(), url: $exchangeURL)
                     case .withdraw:
                         WithdrawUriScan(stack: stack.push(), url: passedURL)
                     case .withdrawExchange:

Required notifications

Address or linkRemarkAdded byNotifiedActions

Relationships

related to 0011621 implementing taler-uri-action "add-exchange" missing 

Activities

Issue History

Date ModifiedUsernameFieldChange
2026-11-11 02:05bot-cgNew Issue
2026-11-11 02:05bot-cgRelationship addedrelated to 0011621
2026-11-11 02:05bot-cgFile Added: before-ios-1.png
2026-11-11 02:05bot-cgFile Added: before-web-1.png
2026-11-11 02:05bot-cgFile Added: before-web-2.png
2026-11-11 02:05bot-cgFile Added: after-ios-1.png
2026-11-11 02:05bot-cgFile Added: after-ios-2.png
2026-11-11 02:05bot-cgFile Added: ios-add-exchange-uri-scanning.patch