taler-ios

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

DebugSettingsView.swift (14194B)


      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 import LocalConsole
     12 
     13 struct DebugSettingsView: View {
     14     private let symLog = SymLogV(0)
     15     let stack: CallStack
     16     let navTitle: String
     17 
     18     @EnvironmentObject private var controller: Controller
     19     @EnvironmentObject private var model: WalletModel
     20 //    @Environment(\.colorSchemeContrast) private var colorSchemeContrast
     21 #if DEBUG
     22     @AppStorage("developerMode") var developerMode: Bool = true
     23 #else
     24     @AppStorage("developerMode") var developerMode: Bool = false
     25 #endif
     26     @AppStorage("logTransactions") var logTransactions: Bool = false
     27     @AppStorage("useHaptics") var useHaptics: Bool = true
     28     @AppStorage("developDelay") var developDelay: Bool = false
     29     @AppStorage("myListStyle") var myListStyle: MyListStyle = .automatic
     30     @AppStorage("minimalistic") var minimalistic: Bool = false
     31     @AppStorage("localConsoleL") var localConsoleL: Bool = false                // for Logs
     32     @AppStorage("localConsoleO") var localConsoleO: Int = 0                     // for Observability
     33 
     34     @State private var checkDisabled = false
     35     @State private var withDrawDisabled = false
     36     @State private var showDevelopItems = false
     37     @State private var showResetAlert: Bool = false
     38     @State private var didReset: Bool = false
     39 
     40     private var dismissAlertButton: some View {
     41         Button("Cancel", role: .cancel) {
     42             showResetAlert = false
     43         }
     44     }
     45     private var resetButton: some View {
     46         Button("Reset", role: .destructive) {                                   // TODO: WalletColors().errorColor
     47             didReset = true
     48             showResetAlert = false
     49             Task { // runs on MainActor
     50                 symLog.log("❗️Reset wallet-core❗️")
     51                 try? await model.resetWalletCore()
     52                 controller.balances.removeAll()
     53             }
     54         }
     55     }
     56     @State private var listID = UUID()
     57 
     58     var body: some View {
     59 #if PRINT_CHANGES
     60         let _ = Self._printChanges()
     61         let _ = symLog.vlog()       // just to get the # to compare it with .onAppear & onDisappear
     62 #endif
     63         let walletCore = WalletCore.shared
     64         Group {
     65             List {
     66                 SettingsToggle(name: String("Developer Mode"), value: $developerMode,
     67                                 id1: "devMode",
     68                         description: String("More information intended for debugging")) { newVal in
     69                     withAnimation(Animation.linear.delay(0.8)) { showDevelopItems = developerMode }
     70                 }
     71                 if showDevelopItems {
     72 #if DEBUG
     73                     SettingsToggle(name: String("Log Transactions"), value: $logTransactions.onChange({ isLogging in
     74                         walletCore.logTransactions = isLogging}),
     75                                     id1: "logTransactions",
     76                             description: String("full log with all tx"))
     77 #endif
     78                     let localConsStr = String("on LocalConsole")
     79                     let observability = String("Observe walletCore")
     80                     SettingsTriState(name: observability, value: $localConsoleO.onChange({ isObserving in
     81                         walletCore.isObserving = isObserving}),
     82                                       id1: "observe",
     83                               description: localConsStr) { isObserving in
     84                         let consoleManager = LCManager.shared
     85                         consoleManager.isVisible = localConsoleO != 0 || localConsoleL
     86                         consoleManager.clear()
     87                     }
     88                     let showLogs = String("Show logs")
     89                     SettingsToggle(name: showLogs, value: $localConsoleL.onChange({ isLogging in
     90                         walletCore.isLogging = isLogging}),
     91                                     id1: "localConsoleL",
     92                             description: localConsStr) { _ in
     93                         let consoleManager = LCManager.shared
     94                         consoleManager.isVisible = localConsoleO != 0 || localConsoleL
     95                         consoleManager.clear()
     96                     }
     97 #if DEBUG
     98                     let banks = ["glstest.taler.net", "taler.fdold.eu", "regio-taler.fdold.eu",
     99                                  "taler.grothoff.org", "taler.ar",
    100                                  "head.taler.net", "test.taler.net", "demo.taler.net", "kyctest.taler.net"]
    101                     ForEach(banks, id: \.self) { bank in
    102                         let urlStr = "https://bank." + bank
    103                         Link(bank, destination: URL(string: urlStr)!)
    104                     }
    105 #endif
    106                 } // showDevelopItems
    107                     SettingsItem(name: String("DEMO"), id1: "demo1with",
    108                           description: String("Get money for testing")) {
    109                         let title = "Withdraw"
    110                         Button(title) {
    111                             withDrawDisabled = true    // don't run twice
    112                             Task { // runs on MainActor
    113                                 symLog.log("Withdraw DEMO KUDOS")
    114                                 let amount = Amount(currency:  DEMOCURRENCY, cent: 11100)
    115                                 try? await model.loadTestKudos(0, amount: amount)
    116                             }
    117                         }
    118                         .buttonStyle(.bordered)
    119                         .disabled(withDrawDisabled)
    120                     }.id("demo1withdraw")
    121                     SettingsItem(name: String("TEST"), id1: "test1with",
    122                           description: String("Get money for testing")) {
    123                         let title = "Withdraw"
    124                         Button(title) {
    125                             withDrawDisabled = true    // don't run twice
    126                             Task { // runs on MainActor
    127                                 symLog.log("Withdraw TESTKUDOS")
    128                                 let cent = UInt64.random(in: 110...195) * 100
    129                                 let amount = Amount(currency:  TESTCURRENCY, cent: cent)
    130                                 try? await model.loadTestKudos(1, amount: amount)
    131                             }
    132                         }
    133                         .buttonStyle(.bordered)
    134                         .disabled(withDrawDisabled)
    135                     }.id("test1withdraw")
    136                 if showDevelopItems {
    137                     SettingsItem(name: String("HEAD"), id1: "head1with",
    138                           description: String("Get money for testing")) {
    139                         let title = "Withdraw"
    140                         Button(title) {
    141                             withDrawDisabled = true    // don't run twice
    142                             Task { // runs on MainActor
    143                                 symLog.log("Withdraw HEAD KUDOS")
    144                                 let amount = Amount(currency:  DEMOCURRENCY, cent: 1100)
    145                                 try? await model.loadTestKudos(2, amount: amount)
    146                             }
    147                         }
    148                         .buttonStyle(.bordered)
    149                         .disabled(withDrawDisabled)
    150                     }.id("head1withdraw")
    151                     SettingsToggle(name: String("Set 2 seconds delay"),
    152                                   value: $developDelay.onChange({ delay in
    153                                             walletCore.developDelay = delay}),
    154                                     id1: "delay",
    155                             description: String("After each wallet-core action"))
    156                         .id("delay")
    157 #if DEBUG
    158                     SettingsItem(name: String("Run Dev Experiment Refresh"),
    159                                   id1: "applyDevExperiment",
    160                           description: "dev-experiment/insert-pending-refresh") {
    161                         let title = "Refresh"
    162                         Button(title) {
    163                             Task { // runs on MainActor
    164                                 symLog.log("running applyDevExperiment Refresh")
    165                                 try? await model.setConfig(setTesting: true)
    166                                 try? await model.devExperimentT(talerUri: "taler://dev-experiment/start-block-refresh")
    167                                 try? await model.devExperimentT(talerUri: "taler://dev-experiment/insert-pending-refresh")
    168                             }
    169                         }
    170                         .buttonStyle(.bordered)
    171                     }.id("Refresh")
    172 #endif
    173                     SettingsItem(name: String("Run Integration Test"),
    174                                   id1: "demo1test",
    175                           description: String("Perform basic test transactions")) {
    176                         let title = "Demo 1"
    177                         Button(title) {
    178                             checkDisabled = true    // don't run twice
    179                             Task { // runs on MainActor
    180                                 symLog.log("running integration test on demo")
    181                                 try? await model.runIntegrationTest(newVersion: false, test: false)
    182                             }
    183                         }
    184                         .buttonStyle(.bordered)
    185                         .disabled(checkDisabled)
    186                     }.id("demo1runTest")
    187                     SettingsItem(name: String("Run Integration Test"),
    188                                   id1: "test1test",
    189                           description: "Perform basic test transactions") {
    190                         let title = "Test 1"
    191                         Button(title) {
    192                             checkDisabled = true    // don't run twice
    193                             Task { // runs on MainActor
    194                                 symLog.log("running integration test on test")
    195                                 try? await model.runIntegrationTest(newVersion: false, test: true)
    196                             }
    197                         }
    198                         .buttonStyle(.bordered)
    199                         .disabled(checkDisabled)
    200                     }.id("test1runTest")
    201                     SettingsItem(name: String("Run Integration Test V2"),
    202                                   id1: "demo2test",
    203                           description: String("Perform more test transactions")) {
    204                         let title = "Demo 2"
    205                         Button(title) {
    206                             checkDisabled = true    // don't run twice
    207                             Task { // runs on MainActor
    208                                 symLog.log("running integration test V2 on demo")
    209                                 try? await model.runIntegrationTest(newVersion: true, test: false)
    210                             }
    211                         }
    212                         .buttonStyle(.bordered)
    213                         .disabled(checkDisabled)
    214                     }.id("demo2runTest")
    215                     SettingsItem(name: String("Run Integration Test V2"),
    216                                   id1: "test2test",
    217                           description: String("Perform more test transactions")) {
    218                         let title = "Test 2"
    219                         Button(title) {
    220                             checkDisabled = true    // don't run twice
    221                             Task { // runs on MainActor
    222                                 symLog.log("running integration test V2 on test")
    223                                 try? await model.runIntegrationTest(newVersion: true, test: true)
    224                             }
    225                         }
    226                         .buttonStyle(.bordered)
    227                         .disabled(checkDisabled)
    228                     }.id("test2runTest")
    229                     SettingsItem(name: String("Run Infinite Transaction Loop"),
    230                                   id1: "runInfinite",
    231                           description: String("Check DB in background")) {
    232                         let title = "Loop"
    233                         Button(title) {
    234                             checkDisabled = true    // don't run twice
    235                             Task { // runs on MainActor
    236                                 symLog.log("Running Infinite Transaction Loop")
    237                                 try? await model.testingInfiniteTransaction(delayMs: 10_000, shouldFetch: true)
    238                             }
    239                         }
    240                         .buttonStyle(.bordered)
    241                         .disabled(checkDisabled)
    242                     }.id("runInfiniteLoop")
    243                     SettingsItem(name: String("Save Logfile"), id1: "save",
    244                           description: String("Help debugging wallet-core")) {
    245                         Button("Save") {
    246                             symLog.log("Saving Log")
    247                             // FIXME: Save Logfile
    248                         }
    249                         .buttonStyle(.bordered)
    250                         .disabled(true)
    251                     }.id("saveLog")
    252                     SettingsItem(name: String("Reset Wallet"), id1: "reset",
    253                           description: String("Throw away all your money")) {
    254                         Button("Reset") {
    255                             showResetAlert = true
    256                         }
    257                         .buttonStyle(.bordered)
    258 //                        .disabled(didReset)
    259                     }.id("resetWallet")
    260                 }
    261             }
    262             .padding(.bottom)
    263             .id(listID)
    264             .listStyle(myListStyle.style).anyView
    265         }
    266         .navigationTitle(navTitle)
    267         .onAppear() {
    268             showDevelopItems = developerMode
    269             DebugViewC.shared.setViewID(VIEW_SETTINGS, stack: stack.push())
    270         }
    271         .onDisappear() {
    272             checkDisabled = false    // reset
    273             withDrawDisabled = false
    274         }
    275         .alert("Reset Wallet",
    276                isPresented: $showResetAlert,
    277                actions: { dismissAlertButton
    278                           resetButton },
    279                message: {   Text(verbatim: "Are you sure you want to reset your wallet?\nThis cannot be reverted, all money will be lost.") })
    280 
    281     } // body
    282 }