gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-ios] branch master updated: basic exchange list


From: gnunet
Subject: [taler-taler-ios] branch master updated: basic exchange list
Date: Tue, 09 Aug 2022 00:00:16 +0200

This is an automated email from the git hooks/post-receive script.

jonathan-buchanan pushed a commit to branch master
in repository taler-ios.

The following commit(s) were added to refs/heads/master by this push:
     new 7db23ac  basic exchange list
7db23ac is described below

commit 7db23acf4f69f07a0fda302b4909284741401fe9
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Mon Aug 8 17:59:59 2022 -0400

    basic exchange list
---
 Taler.xcodeproj/project.pbxproj |  10 ++
 Taler/BackendManager.swift      |  28 +++++
 Taler/ContentView.swift         |   4 +-
 Taler/ExchangeManager.swift     |  55 ++++++++++
 Taler/SettingsView.swift        | 227 ++++++++++++++++++++++++++++++++++++++--
 Taler/WalletBackend.swift       |   7 +-
 iono                            |   2 +-
 7 files changed, 320 insertions(+), 13 deletions(-)

diff --git a/Taler.xcodeproj/project.pbxproj b/Taler.xcodeproj/project.pbxproj
index b1a7e6b..cf2bdb7 100644
--- a/Taler.xcodeproj/project.pbxproj
+++ b/Taler.xcodeproj/project.pbxproj
@@ -10,6 +10,8 @@
                AB1F87C82887C94700AB82A0 /* TalerApp.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = AB1F87C72887C94700AB82A0 /* TalerApp.swift */; };
                AB1F87CA2887D2F400AB82A0 /* ContentView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = AB1F87C92887D2F400AB82A0 /* ContentView.swift 
*/; };
                AB8C3807286A88A600E0A1DD /* WalletBackendTests.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = AB8C3806286A88A500E0A1DD /* 
WalletBackendTests.swift */; };
+               ABB33065289C5BBB00668B42 /* ExchangeManager.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = ABB33064289C5BBB00668B42 /* 
ExchangeManager.swift */; };
+               ABB33067289C658900668B42 /* BackendManager.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = ABB33066289C658900668B42 /* 
BackendManager.swift */; };
                ABB762AD2891059600E88634 /* SettingsView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = ABB762AC2891059600E88634 /* SettingsView.swift 
*/; };
                ABC13AA32859962800D23185 /* taler-swift in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABC13AA22859962800D23185 /* taler-swift */; };
                ABE97B1D286D82BF00580772 /* AnyCodable in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABE97B1C286D82BF00580772 /* AnyCodable */; };
@@ -56,6 +58,8 @@
                AB1F87C92887D2F400AB82A0 /* ContentView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ContentView.swift; sourceTree = "<group>"; };
                AB710490285995B6008B04F0 /* taler-swift */ = {isa = 
PBXFileReference; lastKnownFileType = text; path = "taler-swift"; sourceTree = 
SOURCE_ROOT; };
                AB8C3806286A88A500E0A1DD /* WalletBackendTests.swift */ = {isa 
= PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
WalletBackendTests.swift; sourceTree = "<group>"; };
+               ABB33064289C5BBB00668B42 /* ExchangeManager.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ExchangeManager.swift; sourceTree = "<group>"; };
+               ABB33066289C658900668B42 /* BackendManager.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
BackendManager.swift; sourceTree = "<group>"; };
                ABB762AC2891059600E88634 /* SettingsView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
SettingsView.swift; sourceTree = "<group>"; };
                D11250FF26B12E3200D02E00 /* taler-wallet-embedded.js */ = {isa 
= PBXFileReference; lastKnownFileType = sourcecode.javascript; path = 
"taler-wallet-embedded.js"; sourceTree = "<group>"; };
                D14AFD1D24D232B300C51073 /* Taler.app */ = {isa = 
PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; 
path = Taler.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -136,6 +140,8 @@
                                D14AFD2E24D232B500C51073 /* Info.plist */,
                                AB1F87C72887C94700AB82A0 /* TalerApp.swift */,
                                ABB762AC2891059600E88634 /* SettingsView.swift 
*/,
+                               ABB33064289C5BBB00668B42 /* 
ExchangeManager.swift */,
+                               ABB33066289C658900668B42 /* 
BackendManager.swift */,
                        );
                        path = Taler;
                        sourceTree = "<group>";
@@ -349,6 +355,8 @@
                        files = (
                                AB1F87C82887C94700AB82A0 /* TalerApp.swift in 
Sources */,
                                AB1F87CA2887D2F400AB82A0 /* ContentView.swift 
in Sources */,
+                               ABB33067289C658900668B42 /* 
BackendManager.swift in Sources */,
+                               ABB33065289C5BBB00668B42 /* 
ExchangeManager.swift in Sources */,
                                D1D65B9826992E4600C1012A /* WalletBackend.swift 
in Sources */,
                                ABB762AD2891059600E88634 /* SettingsView.swift 
in Sources */,
                                D14CE1B426C3A2D400612DBE /* BalanceList.swift 
in Sources */,
@@ -535,6 +543,7 @@
                                        
"$(PROJECT_DIR)/iono/ios-node-v8/deps/uv/include",
                                );
                                INFOPLIST_FILE = Taler/Info.plist;
+                               IPHONEOS_DEPLOYMENT_TARGET = 14.0;
                                LD_RUNPATH_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "@executable_path/Frameworks",
@@ -608,6 +617,7 @@
                                        
"$(PROJECT_DIR)/iono/ios-node-v8/deps/uv/include",
                                );
                                INFOPLIST_FILE = Taler/Info.plist;
+                               IPHONEOS_DEPLOYMENT_TARGET = 14.0;
                                LD_RUNPATH_SEARCH_PATHS = (
                                        "$(inherited)",
                                        "@executable_path/Frameworks",
diff --git a/Taler/BackendManager.swift b/Taler/BackendManager.swift
new file mode 100644
index 0000000..8de4472
--- /dev/null
+++ b/Taler/BackendManager.swift
@@ -0,0 +1,28 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2022 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under 
the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import Foundation
+
+class BackendManager: ObservableObject {
+    var backend: WalletBackend
+    
+    @Published var exchangeManager: ExchangeManager
+    
+    init() {
+        self.backend = try! WalletBackend()
+        self.exchangeManager = ExchangeManager(_backend: self.backend)
+    }
+}
diff --git a/Taler/ContentView.swift b/Taler/ContentView.swift
index 415de47..c830692 100644
--- a/Taler/ContentView.swift
+++ b/Taler/ContentView.swift
@@ -22,6 +22,8 @@ struct SidebarItem {
 }
 
 struct ContentView: View {
+    @StateObject var backend: BackendManager = BackendManager()
+    
     @State var sidebarVisible: Bool = false
     var views: [SidebarItem] {[
         SidebarItem(name: "Main",
@@ -33,7 +35,7 @@ struct ContentView: View {
         SidebarItem(name: "Settings",
             view: AnyView(SettingsView {
                 self.sidebarVisible = true
-            }))
+            }.environmentObject(backend)))
     ]}
     @State var currentView: Int = 0
     
diff --git a/Taler/ExchangeManager.swift b/Taler/ExchangeManager.swift
new file mode 100644
index 0000000..2d2e990
--- /dev/null
+++ b/Taler/ExchangeManager.swift
@@ -0,0 +1,55 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2022 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under 
the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import Foundation
+
+typealias ExchangeItem = WalletBackendListExchanges.ExchangeListItem
+
+class ExchangeManager: ObservableObject {
+    var backend: WalletBackend
+    
+    var loading: Bool
+    @Published var exchanges: [ExchangeItem]?
+    
+    init(_backend: WalletBackend) {
+        self.backend = _backend
+        self.loading = false
+        self.exchanges = nil
+    }
+    
+    func updateList() {
+        let listRequest = WalletBackendListExchanges()
+        backend.sendFormattedRequest(request: listRequest) { response, err in
+            self.loading = false
+            if let result = response {
+                // TODO: Use Combine instead.
+                DispatchQueue.main.async {
+                    self.exchanges = result.exchanges
+                }
+            } else {
+                // TODO: Show error.
+            }
+        }
+        self.loading = true
+    }
+    
+    func add(url: String) {
+        let addRequest = WalletBackendAddExchangeRequest(exchangeBaseUrl: url)
+        backend.sendFormattedRequest(request: addRequest) { response, err in
+            // TODO: Show error.
+        }
+    }
+}
diff --git a/Taler/SettingsView.swift b/Taler/SettingsView.swift
index 38cf996..4548f12 100644
--- a/Taler/SettingsView.swift
+++ b/Taler/SettingsView.swift
@@ -1,18 +1,229 @@
-//
-//  SettingsView.swift
-//  Taler
-//
-//  Created by Jonathan Buchanan on 7/27/22.
-//  Copyright © 2022 Taler. All rights reserved.
-//
+/*
+ * This file is part of GNU Taler
+ * (C) 2022 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under 
the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
 
 import SwiftUI
 
+struct TextInputPopup: ViewModifier {
+    @State var exchangeUrl: String = "https://";
+    var onCancel: () -> Void
+    var onOk: (String) -> Void
+    
+    init(cancel: @escaping () -> Void, ok: @escaping (String) -> Void) {
+        self.onCancel = cancel
+        self.onOk = ok
+    }
+    
+    func body(content: Content) -> some View {
+        return content
+            .overlay(
+                VStack {
+                    Text("Add Exchange")
+                    TextField("Exchange URL", text: $exchangeUrl)
+                    HStack {
+                        Button {
+                            self.onCancel()
+                        } label: {
+                            Text("Cancel")
+                        }
+                        Button {
+                            self.onOk(exchangeUrl)
+                        } label: {
+                            Text("Ok")
+                        }
+                    }
+                }
+                    .padding(8)
+                    .frame(width: UIScreen.main.bounds.width - 100, height: 
150, alignment: .center)
+                    .background(Color.green)
+                    .cornerRadius(8)
+            , alignment: .center)
+            .animation(.easeIn)
+    }
+}
+
+extension View {
+    func textInputPopup(cancel: @escaping () -> Void, ok: @escaping (String) 
-> Void, showing: Bool) -> some View {
+        if showing {
+            return AnyView(modifier(TextInputPopup(cancel: cancel, ok: ok)))
+        } else {
+            return AnyView(self)
+        }
+    }
+}
+
+struct ExchangeItemView: View {
+    var exchange: ExchangeItem
+    var body: some View {
+        VStack {
+            Text(exchange.exchangeBaseUrl)
+            Text("Currency: " + exchange.currency)
+        }
+    }
+}
+
+struct ExchangeListView: View {
+    @ObservedObject var exchangeManager: ExchangeManager
+    @State var showPopup: Bool = false
+    
+    var body: some View {
+        if let exchanges = exchangeManager.exchanges {
+            if exchanges.count == 0 {
+                Text("No Exchanges")
+                    .navigationTitle("Exchanges")
+                    .navigationBarItems(trailing: Button(action: {
+                        withAnimation {
+                            showPopup = true
+                        }
+                    }, label: {
+                        Image(systemName: "plus")
+                    }))
+                    .textInputPopup(cancel: {
+                        self.showPopup = false
+                    }, ok: { exchangeUrl in
+                        self.showPopup = false
+                        exchangeManager.add(url: exchangeUrl)
+                        print(exchangeUrl)
+                    }, showing: showPopup)
+            } else {
+                List(exchanges, id: \.self) { exchange in
+                    ExchangeItemView(exchange: exchange)
+                }
+                    .navigationTitle("Exchanges")
+                    .navigationBarItems(trailing: Button(action: {
+                        withAnimation {
+                            showPopup = true
+                        }
+                    }, label: {
+                        Image(systemName: "plus")
+                    }))
+                    .textInputPopup(cancel: {
+                        self.showPopup = false
+                    }, ok: { exchangeUrl in
+                        self.showPopup = false
+                        exchangeManager.add(url: exchangeUrl)
+                        print(exchangeUrl)
+                    }, showing: showPopup)
+            }
+        } else {
+            ProgressView()
+                .navigationTitle("Exchanges")
+                .onAppear {
+                    exchangeManager.updateList()
+                }
+        }
+    }
+}
+
+/*
+ * Exchanges
+ * Manage list of exchanges known to this wallet
+ *
+ * Backup
+ * Last backup: 5 hr. ago
+ *
+ * Developer Mode [toggle]
+ * Shows more information intended for debugging
+ *
+ * Withdraw TESTKUDOS
+ * Get money for testing
+ *
+ * Debug log
+ * View/send internal log
+ *
+ * App Version
+ * v0.9.0-dev.11 (fdroid 11)
+ *
+ * Wallet Core Version
+ * v0.9.0-dev.11
+ *
+ * Supported Exchange Versions
+ * 12:0:0
+ *
+ * Supported Merchant Versions
+ * 2:0:1
+ *
+ * Reset Wallet (dangerous!)
+ * Throws away your money
+ */
+
+struct SettingsItem<Content: View>: View {
+    var name: String
+    var description: String?
+    var content: () -> Content
+    
+    init(name: String, description: String? = nil, @ViewBuilder content: 
@escaping () -> Content) {
+        self.name = name
+        self.description = description
+        self.content = content
+    }
+    
+    var body: some View {
+        HStack {
+            Image(systemName: "line.3.horizontal")
+            VStack {
+                Text(name)
+                    .frame(maxWidth: .infinity, alignment: .leading)
+                    .font(.title2)
+                if let desc = description {
+                    Text(desc)
+                        .frame(maxWidth: .infinity, alignment: .leading)
+                        .font(.caption)
+                }
+            }
+            content()
+        }
+            .padding([.bottom], 8)
+    }
+}
+
 struct SettingsView: View {
+    @EnvironmentObject var backend: BackendManager
+    @AppStorage("developerMode") var developerMode: Bool = false
+    
     var showSidebar: () -> Void
     var body: some View {
         NavigationView {
-            Text("Settings")
+            VStack {
+                SettingsItem(name: "Exchanges", description: "Manage list of 
exchanges known to this wallet") {
+                    NavigationLink {
+                        ExchangeListView(exchangeManager: 
backend.exchangeManager)
+                    } label: {
+                        Text("View")
+                    }
+                }
+                SettingsItem(name: "Developer Mode", description: "Shows more 
information intended for debugging") {
+                    Toggle(isOn: $developerMode) { }
+                }
+                if developerMode {
+                    SettingsItem(name: "App Version") {
+                        Text("v0.9.0-dev.11")
+                    }
+                    SettingsItem(name: "Wallet Core Version") {
+                        Text("v0.9.0-dev.11")
+                    }
+                    SettingsItem(name: "Supported Exchange Versions") {
+                        Text("12:0:0")
+                    }
+                    SettingsItem(name: "Supported Merchant Versions") {
+                        Text("2:0:1")
+                    }
+                }
+                Spacer()
+            }
+                .padding(16)
                 .navigationTitle("Settings")
                 .navigationBarItems(
                     leading: Button(action: self.showSidebar, label: {
diff --git a/Taler/WalletBackend.swift b/Taler/WalletBackend.swift
index 32bd1a9..2e15c1e 100644
--- a/Taler/WalletBackend.swift
+++ b/Taler/WalletBackend.swift
@@ -296,7 +296,7 @@ struct WalletBackendListExchanges: 
WalletBackendFormattedRequest {
         
     }
     
-    struct ExchangeListItem: Decodable {
+    struct ExchangeListItem: Decodable, Hashable {
         var exchangeBaseUrl: String
         var currency: String
         var paytoUris: [String]
@@ -316,7 +316,7 @@ struct WalletBackendListExchanges: 
WalletBackendFormattedRequest {
 }
 
 /// A request to add an exchange.
-struct WalletBackendAddRequest: WalletBackendFormattedRequest {
+struct WalletBackendAddExchangeRequest: WalletBackendFormattedRequest {
     var exchangeBaseUrl: String
     
     struct Args: Encodable {
@@ -328,7 +328,7 @@ struct WalletBackendAddRequest: 
WalletBackendFormattedRequest {
     }
     
     func operation() -> String {
-        return "addRequest"
+        return "addExchange"
     }
     
     func args() -> Args {
@@ -875,6 +875,7 @@ class WalletBackend: IonoMessageHandler {
     }
     
     func handleMessage(message: String) {
+        //print("got message: \(message)")
         do {
             guard let messageData = message.data(using: .utf8) else { throw 
WalletBackendError.deserializationError }
             let data = try JSONSerialization.jsonObject(with: messageData, 
options: .allowFragments) as? [String : Any]
diff --git a/iono b/iono
index 2a43b45..079161b 160000
--- a/iono
+++ b/iono
@@ -1 +1 @@
-Subproject commit 2a43b45c68ddb5a798d7deeeb3fd879304002db6
+Subproject commit 079161b79434e6c121a48a1df3aa95a6185d76dc

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]