damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

WalletView.swift (10052B)


      1 //
      2 //  WalletView.swift
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2023-05-05.
      6 //
      7 
      8 import SwiftUI
      9 
     10 struct WalletView: View {
     11     let damus_state: DamusState
     12     @ObservedObject var model: WalletModel
     13     @ObservedObject var settings: UserSettingsStore
     14     
     15     init(damus_state: DamusState, model: WalletModel? = nil) {
     16         self.damus_state = damus_state
     17         self._model = ObservedObject(wrappedValue: model ?? damus_state.wallet)
     18         self._settings = ObservedObject(wrappedValue: damus_state.settings)
     19     }
     20     
     21     func MainWalletView(nwc: WalletConnectURL) -> some View {
     22         VStack {
     23             if !damus_state.settings.nozaps {
     24                 SupportDamus
     25                 
     26                 Spacer()
     27             }
     28             
     29             VStack(spacing: 5) {
     30                 VStack(spacing: 10) {
     31                     Text("Wallet Relay")
     32                         .fontWeight(.semibold)
     33                         .padding(.top)
     34 
     35                     Divider()
     36 
     37                     RelayView(state: damus_state, relay: nwc.relay, showActionButtons: .constant(false), recommended: false)
     38                 }
     39                 .frame(maxWidth: .infinity, minHeight: 125, alignment: .top)
     40                 .padding(.horizontal, 10)
     41                 .background(DamusColors.neutral1)
     42                 .cornerRadius(10)
     43                 .overlay(
     44                     RoundedRectangle(cornerRadius: 10)
     45                         .stroke(DamusColors.neutral3, lineWidth: 1)
     46                 )
     47                 
     48                 if let lud16 = nwc.lud16 {
     49                     VStack(spacing: 10) {
     50                         Text("Wallet Address")
     51                             .fontWeight(.semibold)
     52                         
     53                         Divider()
     54                         
     55                         Text(verbatim: lud16)
     56                     }
     57                     .frame(maxWidth: .infinity, minHeight: 75, alignment: .center)
     58                     .padding(.horizontal, 10)
     59                     .background(DamusColors.neutral1)
     60                     .cornerRadius(10)
     61                     .overlay(
     62                         RoundedRectangle(cornerRadius: 10)
     63                             .stroke(DamusColors.neutral3, lineWidth: 1)
     64                     )
     65                 }
     66             }
     67             
     68             Button(action: {
     69                 self.model.disconnect()
     70             }) {
     71                 HStack {
     72                     Text(NSLocalizedString("Disconnect Wallet", comment: "Text for button to disconnect from Nostr Wallet Connect lightning wallet."))
     73                 }
     74                 .frame(minWidth: 300, maxWidth: .infinity, maxHeight: 18, alignment: .center)
     75             }
     76             .buttonStyle(GradientButtonStyle())
     77             
     78         }
     79         .navigationTitle(NSLocalizedString("Wallet", comment: "Navigation title for Wallet view"))
     80         .navigationBarTitleDisplayMode(.inline)
     81         .padding()
     82     }
     83     
     84     func donation_binding() -> Binding<Double> {
     85         return Binding(get: {
     86             return Double(model.settings.donation_percent)
     87         }, set: { v in
     88             model.settings.donation_percent = Int(v)
     89         })
     90     }
     91     
     92     static let min_donation: Double = 0.0
     93     static let max_donation: Double = 100.0
     94     
     95     var percent: Double {
     96         Double(model.settings.donation_percent) / 100.0
     97     }
     98     
     99     var tip_msats: String {
    100         let msats = Int64(percent * Double(model.settings.default_zap_amount * 1000))
    101         let s = format_msats_abbrev(msats)
    102         // TODO: fix formatting and remove this hack
    103         let parts = s.split(separator: ".")
    104         if parts.count == 1 {
    105             return s
    106         }
    107         if let end = parts[safe: 1] {
    108             if end.allSatisfy({ c in c.isNumber }) {
    109                 return String(parts[0])
    110             } else {
    111                 return s
    112             }
    113         }
    114         return s
    115     }
    116     
    117     var SupportDamus: some View {
    118         ZStack(alignment: .topLeading) {
    119             RoundedRectangle(cornerRadius: 20)
    120                 .fill(DamusGradient.gradient.opacity(0.5))
    121             
    122             VStack(alignment: .leading, spacing: 20) {
    123                 HStack {
    124                     Image("logo-nobg")
    125                         .resizable()
    126                         .frame(width: 50, height: 50)
    127                     Text("Support Damus", comment: "Text calling for the user to support Damus through zaps")
    128                         .font(.title.bold())
    129                         .foregroundColor(.white)
    130                 }
    131                 
    132                 Text("Help build the future of decentralized communication on the web.", comment: "Text indicating the goal of developing Damus which the user can help with.")
    133                     .fixedSize(horizontal: false, vertical: true)
    134                     .foregroundColor(.white)
    135                 
    136                 Text("An additional percentage of each zap will be sent to support Damus development", comment: "Text indicating that they can contribute zaps to support Damus development.")
    137                     .fixedSize(horizontal: false, vertical: true)
    138                     .foregroundColor(.white)
    139                 
    140                 let binding = donation_binding()
    141                 
    142                 HStack {
    143                     Slider(value: binding,
    144                            in: WalletView.min_donation...WalletView.max_donation,
    145                            label: {  })
    146                     Text("\(Int(binding.wrappedValue))%", comment: "Percentage of additional zap that should be sent to support Damus development.")
    147                         .font(.title.bold())
    148                         .foregroundColor(.white)
    149                         .frame(width: 80)
    150                 }
    151                 
    152                 HStack{
    153                     Spacer()
    154                     
    155                     VStack {
    156                         HStack {
    157                             Text("\(Image("zap.fill")) \(format_msats_abbrev(Int64(model.settings.default_zap_amount) * 1000))")
    158                                 .font(.title)
    159                                 .foregroundColor(percent == 0 ? .gray : .yellow)
    160                                 .frame(width: 120)
    161                         }
    162                         
    163                         Text("Zap", comment: "Text underneath the number of sats indicating that it's the amount used for zaps.")
    164                             .foregroundColor(.white)
    165                     }
    166                     Spacer()
    167                     
    168                     Text(verbatim: "+")
    169                         .font(.title)
    170                         .foregroundColor(.white)
    171                     Spacer()
    172                     
    173                     VStack {
    174                         HStack {
    175                             Text("\(Image("zap.fill")) \(tip_msats)")
    176                                 .font(.title)
    177                                 .foregroundColor(percent == 0 ? .gray : Color.yellow)
    178                                 .frame(width: 120)
    179                         }
    180                         
    181                         Text(verbatim: percent == 0 ? "🩶" : "💜")
    182                             .foregroundColor(.white)
    183                     }
    184                     Spacer()
    185                 }
    186                 
    187                 EventProfile(damus_state: damus_state, pubkey: damus_state.pubkey, size: .small)
    188             }
    189             .padding(25)
    190         }
    191         .frame(height: 370)
    192     }
    193     
    194     var body: some View {
    195         switch model.connect_state {
    196         case .new:
    197             ConnectWalletView(model: model, nav: damus_state.nav)
    198         case .none:
    199             ConnectWalletView(model: model, nav: damus_state.nav)
    200         case .existing(let nwc):
    201             MainWalletView(nwc: nwc)
    202                 .onAppear() {
    203                     model.initial_percent = settings.donation_percent
    204                 }
    205                 .onChange(of: settings.donation_percent) { p in
    206                     let profile_txn = damus_state.profiles.lookup(id: damus_state.pubkey)
    207                     guard let profile = profile_txn?.unsafeUnownedValue else {
    208                         return
    209                     }
    210                     
    211                     let prof = Profile(name: profile.name, display_name: profile.display_name, about: profile.about, picture: profile.picture, banner: profile.banner, website: profile.website, lud06: profile.lud06, lud16: profile.lud16, nip05: profile.nip05, damus_donation: p, reactions: profile.reactions)
    212 
    213                     notify(.profile_updated(.manual(pubkey: self.damus_state.pubkey, profile: prof)))
    214                 }
    215                 .onDisappear {
    216                     let profile_txn = damus_state.profiles.lookup(id: damus_state.pubkey)
    217                     
    218                     guard let keypair = damus_state.keypair.to_full(),
    219                           let profile = profile_txn?.unsafeUnownedValue,
    220                           model.initial_percent != profile.damus_donation
    221                     else {
    222                         return
    223                     }
    224                     
    225                     let prof = Profile(name: profile.name, display_name: profile.display_name, about: profile.about, picture: profile.picture, banner: profile.banner, website: profile.website, lud06: profile.lud06, lud16: profile.lud16, nip05: profile.nip05, damus_donation: settings.donation_percent, reactions: profile.reactions)
    226 
    227                     guard let meta = make_metadata_event(keypair: keypair, metadata: prof) else {
    228                         return
    229                     }
    230                     damus_state.postbox.send(meta)
    231                 }
    232         }
    233     }
    234 }
    235 
    236 let test_wallet_connect_url = WalletConnectURL(pubkey: test_pubkey, relay: .init("wss://relay.damus.io")!, keypair: test_damus_state.keypair.to_full()!, lud16: "jb55@sendsats.com")
    237 
    238 struct WalletView_Previews: PreviewProvider {
    239     static let tds = test_damus_state
    240     static var previews: some View {
    241         WalletView(damus_state: tds, model: WalletModel(state: .existing(test_wallet_connect_url), settings: tds.settings))
    242     }
    243 }