InvoiceView.swift (4399B)
1 // 2 // InvoiceView.swift 3 // damus 4 // 5 // Created by William Casarin on 2022-10-18. 6 // 7 8 import SwiftUI 9 10 struct InvoiceView: View { 11 @Environment(\.colorScheme) var colorScheme 12 let our_pubkey: Pubkey 13 let invoice: Invoice 14 @State var showing_select_wallet: Bool = false 15 @State var copied = false 16 let settings: UserSettingsStore 17 18 var CopyButton: some View { 19 Button { 20 copied = true 21 DispatchQueue.main.asyncAfter(deadline: .now() + 3) { 22 copied = false 23 } 24 UIImpactFeedbackGenerator(style: .medium).impactOccurred() 25 UIPasteboard.general.string = invoice.string 26 } label: { 27 if !copied { 28 Image("copy2") 29 .foregroundColor(.gray) 30 } else { 31 Image("check-circle") 32 .foregroundColor(DamusColors.green) 33 } 34 } 35 } 36 37 var PayButton: some View { 38 Button { 39 if settings.show_wallet_selector { 40 present_sheet(.select_wallet(invoice: invoice.string)) 41 } else { 42 do { 43 try open_with_wallet(wallet: settings.default_wallet.model, invoice: invoice.string) 44 } 45 catch { 46 present_sheet(.select_wallet(invoice: invoice.string)) 47 } 48 } 49 } label: { 50 RoundedRectangle(cornerRadius: 20, style: .circular) 51 .foregroundColor(colorScheme == .light ? .black : .white) 52 .overlay { 53 Text("Pay", comment: "Button to pay a Lightning invoice.") 54 .fontWeight(.medium) 55 .foregroundColor(colorScheme == .light ? .white : .black) 56 } 57 } 58 .onTapGesture { 59 // Temporary solution so that the "pay" button can be clicked (Yes we need an empty tap gesture) 60 print("pay button tap") 61 } 62 } 63 64 var body: some View { 65 ZStack { 66 RoundedRectangle(cornerRadius: 10) 67 .foregroundColor(.secondary.opacity(0.1)) 68 69 VStack(alignment: .leading, spacing: 12) { 70 HStack { 71 Label("", image: "zap.fill") 72 .foregroundColor(.orange) 73 Text("Lightning Invoice", comment: "Indicates that the view is for paying a Lightning invoice.") 74 Spacer() 75 CopyButton 76 } 77 Divider() 78 Text(invoice.description_string) 79 Text(invoice.amount.amount_sats_str()) 80 .font(.title) 81 PayButton 82 .frame(height: 50) 83 .zIndex(10.0) 84 } 85 .padding(30) 86 } 87 } 88 } 89 90 enum OpenWalletError: Error { 91 case no_wallet_to_open 92 case store_link_invalid 93 case system_cannot_open_store_link 94 } 95 96 func open_with_wallet(wallet: Wallet.Model, invoice: String) throws { 97 if let url = URL(string: "\(wallet.link)\(invoice)"), this_app.canOpenURL(url) { 98 this_app.open(url) 99 } else { 100 guard let store_link = wallet.appStoreLink else { 101 throw OpenWalletError.no_wallet_to_open 102 } 103 104 guard let url = URL(string: store_link) else { 105 throw OpenWalletError.store_link_invalid 106 } 107 108 guard this_app.canOpenURL(url) else { 109 throw OpenWalletError.system_cannot_open_store_link 110 } 111 112 this_app.open(url) 113 } 114 } 115 116 117 let test_invoice = Invoice(description: .description("this is a description"), amount: .specific(10000), string: "lnbc100n1p357sl0sp5t9n56wdztun39lgdqlr30xqwksg3k69q4q2rkr52aplujw0esn0qpp5mrqgljk62z20q4nvgr6lzcyn6fhylzccwdvu4k77apg3zmrkujjqdpzw35xjueqd9ejqcfqv3jhxcmjd9c8g6t0dcxqyjw5qcqpjrzjqt56h4gvp5yx36u2uzqa6qwcsk3e2duunfxppzj9vhypc3wfe2wswz607uqq3xqqqsqqqqqqqqqqqlqqyg9qyysgqagx5h20aeulj3gdwx3kxs8u9f4mcakdkwuakasamm9562ffyr9en8yg20lg0ygnr9zpwp68524kmda0t5xp2wytex35pu8hapyjajxqpsql29r", expiry: 604800, payment_hash: Data(), created_at: 1666139119) 118 119 struct InvoiceView_Previews: PreviewProvider { 120 static var previews: some View { 121 InvoiceView(our_pubkey: .empty, invoice: test_invoice, settings: test_damus_state.settings) 122 .frame(width: 300, height: 200) 123 } 124 }