damus

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

commit 0384191060b044249bfe94ff9e85222c9e2922ff
parent 7bee8fd0d13ca4612e4de19aaad3fb5a05c432a0
Author: William Casarin <jb55@jb55.com>
Date:   Fri, 30 Dec 2022 12:41:11 -0800

Improved Wallet Selector

Diffstat:
Mdamus.xcodeproj/project.pbxproj | 8++++++++
Mdamus/Components/InvoiceView.swift | 17+++++++++++++++--
Mdamus/ContentView.swift | 3++-
Adamus/Models/UserSettingsStore.swift | 32++++++++++++++++++++++++++++++++
Adamus/Models/Wallet.swift | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdamus/Util/Constants.swift | 15---------------
Mdamus/Views/ConfigView.swift | 14+++++++++++++-
Mdamus/Views/ProfileView.swift | 2++
Mdamus/Views/SelectWalletView.swift | 46++++++++++++++++++++++------------------------
9 files changed, 166 insertions(+), 43 deletions(-)

diff --git a/damus.xcodeproj/project.pbxproj b/damus.xcodeproj/project.pbxproj @@ -132,7 +132,9 @@ 4CEE2AF7280B2DEA00AB5EEF /* ProfileName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */; }; 4CEE2AF9280B2EAC00AB5EEF /* PowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */; }; 4CEE2B02280B39E800AB5EEF /* EventActionBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */; }; + 4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4FE60CDC295E1C5E00105A1F /* Wallet.swift */; }; 6C7DE41F2955169800E66263 /* Vault in Frameworks */ = {isa = PBXBuildFile; productRef = 6C7DE41E2955169800E66263 /* Vault */; }; + BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA693073295D649800ADDB87 /* UserSettingsStore.swift */; }; BAB68BED29543FA3007BA466 /* SelectWalletView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */; }; E990020F2955F837003BBC5A /* EditMetadataView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E990020E2955F837003BBC5A /* EditMetadataView.swift */; }; E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */; }; @@ -316,6 +318,8 @@ 4CEE2AF6280B2DEA00AB5EEF /* ProfileName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileName.swift; sourceTree = "<group>"; }; 4CEE2AF8280B2EAC00AB5EEF /* PowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowView.swift; sourceTree = "<group>"; }; 4CEE2B01280B39E800AB5EEF /* EventActionBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventActionBar.swift; sourceTree = "<group>"; }; + 4FE60CDC295E1C5E00105A1F /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; }; + BA693073295D649800ADDB87 /* UserSettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSettingsStore.swift; sourceTree = "<group>"; }; BAB68BEC29543FA3007BA466 /* SelectWalletView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectWalletView.swift; sourceTree = "<group>"; }; E990020E2955F837003BBC5A /* EditMetadataView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditMetadataView.swift; sourceTree = "<group>"; }; E9E4ED0A295867B900DD7078 /* ThreadV2View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadV2View.swift; sourceTree = "<group>"; }; @@ -442,6 +446,8 @@ 4C64987D286D082C00EAE2B3 /* DirectMessagesModel.swift */, 4C216F372871EDE300040376 /* DirectMessageModel.swift */, 4C99737A28C92A9200E53835 /* ChatroomMetadata.swift */, + BA693073295D649800ADDB87 /* UserSettingsStore.swift */, + 4FE60CDC295E1C5E00105A1F /* Wallet.swift */, ); path = Models; sourceTree = "<group>"; @@ -806,6 +812,7 @@ 4C363A8428233689006E126D /* Parser.swift in Sources */, 4CE4F9E328528C5200C00DD9 /* AddRelayView.swift in Sources */, 4C363A9A28283854006E126D /* Reply.swift in Sources */, + BA693074295D649800ADDB87 /* UserSettingsStore.swift in Sources */, 4C90BD18283A9EE5008EE7EF /* LoginView.swift in Sources */, 4C3EA66828FF5F9900C48A62 /* hex.c in Sources */, E9E4ED0B295867B900DD7078 /* ThreadV2View.swift in Sources */, @@ -876,6 +883,7 @@ 4CACA9D5280C31E100D9BBE8 /* ReplyView.swift in Sources */, 4C0A3F97280F8E02000448DE /* ThreadView.swift in Sources */, 4C06670B28FDE64700038D2A /* damus.c in Sources */, + 4FE60CDD295E1C5E00105A1F /* Wallet.swift in Sources */, 4C99737B28C92A9200E53835 /* ChatroomMetadata.swift in Sources */, 4C75EFA427FA577B0006080F /* PostView.swift in Sources */, 4C75EFB528049D790006080F /* Relay.swift in Sources */, diff --git a/damus/Components/InvoiceView.swift b/damus/Components/InvoiceView.swift @@ -10,15 +10,28 @@ import SwiftUI struct InvoiceView: View { @Environment(\.colorScheme) var colorScheme + @Environment(\.openURL) private var openURL let invoice: Invoice @State var showingSelectWallet: Bool = false @State var inv: String = "" + @ObservedObject var user_settings = UserSettingsStore() var PayButton: some View { Button { inv = invoice.string - showingSelectWallet = true + if user_settings.showWalletSelector { + showingSelectWallet = true + } else { + let walletModel = user_settings.defaultWallet.model + if let url = URL(string: "\(walletModel.link)\(inv)"), UIApplication.shared.canOpenURL(url) { + openURL(url) + } else { + if let url = URL(string: walletModel.appStoreLink), UIApplication.shared.canOpenURL(url) { + openURL(url) + } + } + } } label: { RoundedRectangle(cornerRadius: 20) .foregroundColor(colorScheme == .light ? .black : .white) @@ -56,7 +69,7 @@ struct InvoiceView: View { .padding(30) } .sheet(isPresented: $showingSelectWallet, onDismiss: {showingSelectWallet = false}) { - SelectWalletView(showingSelectWallet: $showingSelectWallet, invoice: $inv) + SelectWalletView(showingSelectWallet: $showingSelectWallet, invoice: $inv).environmentObject(user_settings) } } } diff --git a/damus/ContentView.swift b/damus/ContentView.swift @@ -72,6 +72,7 @@ struct ContentView: View { @State var search_open: Bool = false @State var filter_state : FilterState = .posts_and_replies @StateObject var home: HomeModel = HomeModel() + @StateObject var user_settings = UserSettingsStore() // connect retry timer let timer = Timer.publish(every: 4, on: .main, in: .common).autoconnect() @@ -219,7 +220,7 @@ struct ContentView: View { .foregroundColor(.gray) } - NavigationLink(destination: ConfigView(state: damus_state!)) { + NavigationLink(destination: ConfigView(state: damus_state!).environmentObject(user_settings)) { Label("", systemImage: "gear") } .buttonStyle(PlainButtonStyle()) diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift @@ -0,0 +1,32 @@ +// +// UserSettingsStore.swift +// damus +// +// Created by Suhail Saqan on 12/29/22. +// + +import Foundation + +class UserSettingsStore: ObservableObject { + @Published var defaultWallet: Wallet { + didSet { + UserDefaults.standard.set(defaultWallet.rawValue, forKey: "default_wallet") + } + } + + @Published var showWalletSelector: Bool { + didSet { + UserDefaults.standard.set(showWalletSelector, forKey: "show_wallet_selector") + } + } + + init() { + if let defaultWalletName = UserDefaults.standard.string(forKey: "default_wallet"), + let defaultWallet = Wallet(rawValue: defaultWalletName) { + self.defaultWallet = defaultWallet + } else { + self.defaultWallet = .systemdefaultwallet + } + self.showWalletSelector = UserDefaults.standard.object(forKey: "show_wallet_selector") as? Bool ?? true + } +} diff --git a/damus/Models/Wallet.swift b/damus/Models/Wallet.swift @@ -0,0 +1,72 @@ +// +// Wallet.swift +// damus +// +// Created by Benjamin Hakes on 12/29/22. +// + +import Foundation + +enum Wallet: String, CaseIterable, Identifiable { + var id: String { self.rawValue } + + struct Model: Identifiable, Hashable { + var id: String { self.tag } + var index: Int + var tag: String + var displayName : String + var link : String + var appStoreLink : String + var image: String + } + + // New url prefixes needed to be added to LSApplicationQueriesSchemes + case systemdefaultwallet + case strike + case cashapp + case muun + case bluewallet + case walletofsatoshi + case zebedee + case zeusln + case lnlink + case phoenix + + var model: Model { + switch self { + case .systemdefaultwallet: + return .init(index: -1, tag: "systemdefaultwallet", displayName: "Local default", + link: "lightning:", appStoreLink: "lightning:", image: "") + case .strike: + return .init(index: 0, tag: "strike", displayName: "Strike", link: "strike:", + appStoreLink: "https://apps.apple.com/us/app/strike-bitcoin-payments/id1488724463", image: "strike") + case .cashapp: + return .init(index: 1, tag: "cashapp", displayName: "Cash App", link: "squarecash://", + appStoreLink: "https://apps.apple.com/us/app/cash-app/id711923939", image: "cashapp") + case .muun: + return .init(index: 2, tag: "muun", displayName: "Muun", link: "muun:", appStoreLink: "https://apps.apple.com/us/app/muun-wallet/id1482037683", image: "muun") + case .bluewallet: + return .init(index: 3, tag: "bluewallet", displayName: "Blue Wallet", link: "bluewallet:lightning:", + appStoreLink: "https://apps.apple.com/us/app/bluewallet-bitcoin-wallet/id1376878040", image: "bluewallet") + case .walletofsatoshi: + return .init(index: 4, tag: "walletofsatoshi", displayName: "Wallet Of Satoshi", link: "walletofsatoshi:lightning:", + appStoreLink: "https://apps.apple.com/us/app/wallet-of-satoshi/id1438599608", image: "walletofsatoshi") + case .zebedee: + return .init(index: 5, tag: "zebedee", displayName: "Zebedee", link: "zebedee:lightning:", + appStoreLink: "https://apps.apple.com/us/app/zebedee-wallet/id1484394401", image: "zebedee") + case .zeusln: + return .init(index: 6, tag: "zeusln", displayName: "Zeus LN", link: "zeusln:lightning:", + appStoreLink: "https://apps.apple.com/us/app/zeus-ln/id1456038895", image: "zeusln") + case .lnlink: + return .init(index: 7, tag: "lnlink", displayName: "LNLink", link: "lnlink:lightning:", + appStoreLink: "https://testflight.apple.com/join/aNY4yuuZ", image: "lnlink") + case .phoenix: + return .init(index: 8, tag: "phoenix", displayName: "Phoenix", link: "phoenix://", + appStoreLink: "https://apps.apple.com/us/app/phoenix-wallet/id1544097028", image: "phoenix") + } + } + + static var allModels: [Model] { + return Self.allCases.map { $0.model } + } +} diff --git a/damus/Util/Constants.swift b/damus/Util/Constants.swift @@ -24,19 +24,4 @@ public class Constants { NostrEvent(id: UUID().description, content: "Hello World! This is so cool!", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"), NostrEvent(id: UUID().description, content: "Bonjour Le Monde", pubkey: "3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"), ] - - // New url prefixes needed to be added to LSApplicationQueriesSchemes - static let WALLETS = """ - [ - {"id": 0, "name": "Strike", "link": "strike:", "appStoreLink": "https://apps.apple.com/us/app/strike-bitcoin-payments/id1488724463", "image": "strike"}, - {"id": 1, "name": "Cash App", "link": "squarecash://", "appStoreLink": "https://apps.apple.com/us/app/cash-app/id711923939", "image": "cashapp"}, - {"id": 2, "name": "Muun", "link": "muun:", "appStoreLink": "https://apps.apple.com/us/app/muun-wallet/id1482037683", "image": "muun"}, - {"id": 3, "name": "Blue Wallet", "link": "bluewallet:lightning:", "appStoreLink": "https://apps.apple.com/us/app/bluewallet-bitcoin-wallet/id1376878040", "image": "bluewallet"}, - {"id": 4, "name": "Wallet Of Satoshi", "link": "walletofsatoshi:lightning:", "appStoreLink": "https://apps.apple.com/us/app/wallet-of-satoshi/id1438599608", "image": "walletofsatoshi"}, - {"id": 5, "name": "Zebedee", "link": "zebedee:lightning:", "appStoreLink": "https://apps.apple.com/us/app/zebedee-wallet/id1484394401", "image": "zebedee"}, - {"id": 6, "name": "Zeus LN", "link": "zeusln:lightning:", "appStoreLink": "https://apps.apple.com/us/app/zeus-ln/id1456038895", "image": "zeusln"}, - {"id": 7, "name": "LNLink", "link": "lnlink:lightning:", "appStoreLink": "https://testflight.apple.com/join/aNY4yuuZ", "image": "lnlink"}, - {"id": 8, "name": "Phoenix", "link": "phoenix://", "appStoreLink": "https://apps.apple.com/us/app/phoenix-wallet/id1544097028", "image": "phoenix"}, - ] - """.data(using: .utf8)! } diff --git a/damus/Views/ConfigView.swift b/damus/Views/ConfigView.swift @@ -17,8 +17,9 @@ struct ConfigView: View { @State var privkey: String @State var privkey_copied: Bool = false @State var pubkey_copied: Bool = false - + @State var allWallets: [Wallet] = Wallet.allCases @State var relays: [RelayDescriptor] + @EnvironmentObject var user_settings: UserSettingsStore let generator = UIImpactFeedbackGenerator(style: .light) @@ -93,6 +94,17 @@ struct ConfigView: View { } } + Section("Wallet Selector") { + Toggle("Show wallet selector", isOn: $user_settings.showWalletSelector).toggleStyle(.switch) + Picker("Select default wallet", + selection: $user_settings.defaultWallet) { + ForEach(allWallets, id: \.self) { wallet in + Text(wallet.model.displayName) + .tag(wallet.model.tag) + } + } + } + Section("Reset") { Button("Logout") { confirm_logout = true diff --git a/damus/Views/ProfileView.swift b/damus/Views/ProfileView.swift @@ -118,6 +118,7 @@ struct ProfileView: View { @State private var selected_tab: ProfileTab = .posts @StateObject var profile: ProfileModel @StateObject var followers: FollowersModel + @StateObject var user_settings = UserSettingsStore() @State private var showingEditProfile = false @State var showingSelectWallet: Bool = false @State var inv: String = "" @@ -150,6 +151,7 @@ struct ProfileView: View { } }.sheet(isPresented: $showingSelectWallet, onDismiss: {showingSelectWallet = false}) { SelectWalletView(showingSelectWallet: $showingSelectWallet, invoice: $inv) + .environmentObject(user_settings) } } diff --git a/damus/Views/SelectWalletView.swift b/damus/Views/SelectWalletView.swift @@ -7,24 +7,16 @@ import SwiftUI -struct WalletItem : Decodable, Identifiable, Hashable { - var id: Int - var name : String - var link : String - var appStoreLink : String - var image: String -} - struct SelectWalletView: View { @Binding var showingSelectWallet: Bool @Binding var invoice: String @Environment(\.openURL) private var openURL @State var invoice_copied: Bool = false + @EnvironmentObject var user_settings: UserSettingsStore + @State var allWalletModels: [Wallet.Model] = Wallet.allModels let generator = UIImpactFeedbackGenerator(style: .light) - let walletItems = try! JSONDecoder().decode([WalletItem].self, from: Constants.WALLETS) - var body: some View { NavigationView { Form { @@ -43,21 +35,26 @@ struct SelectWalletView: View { generator.impactOccurred() } } - Section("Select a lightning wallet"){ - List{ - Button() { - if let url = URL(string: "lightning:\(invoice)"), UIApplication.shared.canOpenURL(url) { + Section("Select a lightning wallet"){ + List{ + Button() { + let walletModel = user_settings.defaultWallet.model + if let url = URL(string: "\(walletModel.link)\(invoice)"), UIApplication.shared.canOpenURL(url) { + openURL(url) + } else { + if let url = URL(string: walletModel.appStoreLink), UIApplication.shared.canOpenURL(url) { openURL(url) } - } label: { - HStack { - Text("Default Wallet").font(.body).foregroundColor(.blue) - } - }.buttonStyle(.plain) - ForEach(walletItems, id: \.self) { wallet in + } + } label: { + HStack { + Text("Default Wallet").font(.body).foregroundColor(.blue) + } + }.buttonStyle(.plain) + List($allWalletModels) { $wallet in + if wallet.index >= 0 { Button() { if let url = URL(string: "\(wallet.link)\(invoice)"), UIApplication.shared.canOpenURL(url) { - print("opening wallet url \(url)") openURL(url) } else { if let url = URL(string: wallet.appStoreLink), UIApplication.shared.canOpenURL(url) { @@ -67,12 +64,13 @@ struct SelectWalletView: View { } label: { HStack { Image(wallet.image).resizable().frame(width: 32.0, height: 32.0,alignment: .center).cornerRadius(5) - Text(wallet.name).font(.body) + Text(wallet.displayName).font(.body) } }.buttonStyle(.plain) } - }.padding(.vertical, 2.5) - } + } + }.padding(.vertical, 2.5) + } }.navigationBarTitle(Text("Pay the lightning invoice"), displayMode: .inline).navigationBarItems(trailing: Button(action: { self.showingSelectWallet = false }) {