diff --git a/LDKNodeMonday.xcodeproj/project.pbxproj b/LDKNodeMonday.xcodeproj/project.pbxproj index e611039..7924b49 100644 --- a/LDKNodeMonday.xcodeproj/project.pbxproj +++ b/LDKNodeMonday.xcodeproj/project.pbxproj @@ -25,7 +25,6 @@ AE060C382C051B59006724F1 /* LDKNode in Frameworks */ = {isa = PBXBuildFile; productRef = AE060C372C051B59006724F1 /* LDKNode */; }; AE0BD4AC2B598C3F00B9901E /* UInt32+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE0BD4AB2B598C3F00B9901E /* UInt32+Extensions.swift */; }; AE17E8DA29A402E30058C9C9 /* LDKNodeMondayApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE17E8D929A402E30058C9C9 /* LDKNodeMondayApp.swift */; }; - AE17E8DC29A402E30058C9C9 /* AddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE17E8DB29A402E30058C9C9 /* AddressView.swift */; }; AE17E8DE29A402E40058C9C9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AE17E8DD29A402E40058C9C9 /* Assets.xcassets */; }; AE17E8E129A402E40058C9C9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AE17E8E029A402E40058C9C9 /* Preview Assets.xcassets */; }; AE17E90D29A42D430058C9C9 /* LightningNodeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE17E90C29A42D430058C9C9 /* LightningNodeService.swift */; }; @@ -39,7 +38,6 @@ AE49E84C2A24F96F002623E8 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E84B2A24F96F002623E8 /* Constants.swift */; }; AE49E8522A253618002623E8 /* StartViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E8512A253618002623E8 /* StartViewModel.swift */; }; AE49E8542A253647002623E8 /* BitcoinViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E8532A253647002623E8 /* BitcoinViewModel.swift */; }; - AE49E8562A253674002623E8 /* AddressViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E8552A253674002623E8 /* AddressViewModel.swift */; }; AE49E8582A2536B4002623E8 /* ChannelsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E8572A2536B4002623E8 /* ChannelsListViewModel.swift */; }; AE49E85A2A2536D4002623E8 /* ChannelAddViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E8592A2536D4002623E8 /* ChannelAddViewModel.swift */; }; AE49E85C2A2536FB002623E8 /* ChannelDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE49E85B2A2536FB002623E8 /* ChannelDetailViewModel.swift */; }; @@ -108,7 +106,6 @@ AE0BD4AB2B598C3F00B9901E /* UInt32+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt32+Extensions.swift"; sourceTree = ""; }; AE17E8D629A402E30058C9C9 /* LDKNodeMonday.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LDKNodeMonday.app; sourceTree = BUILT_PRODUCTS_DIR; }; AE17E8D929A402E30058C9C9 /* LDKNodeMondayApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LDKNodeMondayApp.swift; sourceTree = ""; }; - AE17E8DB29A402E30058C9C9 /* AddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressView.swift; sourceTree = ""; }; AE17E8DD29A402E40058C9C9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; AE17E8E029A402E40058C9C9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; AE17E90C29A42D430058C9C9 /* LightningNodeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LightningNodeService.swift; sourceTree = ""; }; @@ -121,7 +118,6 @@ AE49E84B2A24F96F002623E8 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; AE49E8512A253618002623E8 /* StartViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StartViewModel.swift; sourceTree = ""; }; AE49E8532A253647002623E8 /* BitcoinViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitcoinViewModel.swift; sourceTree = ""; }; - AE49E8552A253674002623E8 /* AddressViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressViewModel.swift; sourceTree = ""; }; AE49E8572A2536B4002623E8 /* ChannelsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelsListViewModel.swift; sourceTree = ""; }; AE49E8592A2536D4002623E8 /* ChannelAddViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelAddViewModel.swift; sourceTree = ""; }; AE49E85B2A2536FB002623E8 /* ChannelDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelDetailViewModel.swift; sourceTree = ""; }; @@ -246,6 +242,14 @@ path = LightningNodesService; sourceTree = ""; }; + AE43F27A2C7E529C00406326 /* Send */ = { + isa = PBXGroup; + children = ( + AE551D482B8ECEB00034B61E /* AmountViewModel.swift */, + ); + path = Send; + sourceTree = ""; + }; AE49E86D2A253A9A002623E8 /* Channel */ = { isa = PBXGroup; children = ( @@ -271,7 +275,6 @@ children = ( AE80C2012C4AB38D006E7193 /* BIP21ViewModel.swift */, AE028A292B96328600B336E7 /* JITInvoiceViewModel.swift */, - AE49E8552A253674002623E8 /* AddressViewModel.swift */, ); path = Receive; sourceTree = ""; @@ -305,8 +308,8 @@ AE00550F2B479F1100100797 /* OnboardingViewModel.swift */, AE49E8512A253618002623E8 /* StartViewModel.swift */, AE49E8532A253647002623E8 /* BitcoinViewModel.swift */, - AE551D482B8ECEB00034B61E /* AmountViewModel.swift */, AE551D452B8ECE180034B61E /* Payments */, + AE43F27A2C7E529C00406326 /* Send */, AE49E8722A253AD5002623E8 /* Receive */, ); path = Home; @@ -363,7 +366,6 @@ AEBFD8B52B8BABC00024E3F7 /* ReceiveView.swift */, AE80C1FF2C4AB360006E7193 /* BIP21View.swift */, AEA057EC2B912FEA00DB1096 /* JITInvoiceView.swift */, - AE17E8DB29A402E30058C9C9 /* AddressView.swift */, ); path = Receive; sourceTree = ""; @@ -604,7 +606,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - AE49E8562A253674002623E8 /* AddressViewModel.swift in Sources */, AE7096352B5C205F0038BE56 /* PriceServiceError.swift in Sources */, AE186B8E2A1540B700338463 /* StartView.swift in Sources */, AEDF47F32B3FBAB900145D64 /* Notification+Extensions.swift in Sources */, @@ -634,7 +635,6 @@ AEDF76022B5C6863002DDEE1 /* Optional+Extensions.swift in Sources */, AE7096382B5C208A0038BE56 /* Price.swift in Sources */, AE49E86C2A253A32002623E8 /* NodeIDViewModel.swift in Sources */, - AE17E8DC29A402E30058C9C9 /* AddressView.swift in Sources */, AEBAA48D2A01A93B0042EA82 /* PeerView.swift in Sources */, AE028A242B96316B00B336E7 /* ReceiveOption.swift in Sources */, AEDF76062B5C68A0002DDEE1 /* ChannelDetailsFormatted.swift in Sources */, diff --git a/LDKNodeMonday/Extensions/String+Extensions.swift b/LDKNodeMonday/Extensions/String+Extensions.swift index 49570ce..62cd8ae 100644 --- a/LDKNodeMonday/Extensions/String+Extensions.swift +++ b/LDKNodeMonday/Extensions/String+Extensions.swift @@ -156,10 +156,10 @@ extension String { } if let offer = bolt12Offer { - return processLightningAddress(offer) + return processLightningAddress(offer, amount: amount) } if let invoice = bolt11Invoice { - return processLightningAddress(invoice) + return processLightningAddress(invoice, amount: amount) } return (bitcoinAddress, amount, .isBitcoin) } @@ -171,9 +171,9 @@ extension String { return processBIP21(self, spendableBalance: spendableBalance) } else if self.lowercased().starts(with: "lightning:") { let invoice = String(self.dropFirst(10)) // Remove "lightning:" prefix - return processLightningAddress(invoice) + return processLightningAddress(invoice, amount: "0") } else if self.lowercased().starts(with: "lnbc") || self.lowercased().starts(with: "lntb") { - return processLightningAddress(self) + return processLightningAddress(self, amount: "0") } else if self.isBitcoinAddress { return processBitcoinAddress(spendableBalance) } else if self.starts(with: "lnurl") { @@ -195,14 +195,17 @@ extension String { } } - private func processLightningAddress(_ address: String) -> (String, String, Payment) { + private func processLightningAddress(_ address: String, amount: String) -> ( + String, String, Payment + ) { let sanitizedAddress = address.replacingOccurrences(of: "lightning:", with: "") if sanitizedAddress.lowercased().starts(with: "lno") { - return (sanitizedAddress, "0", .isLightning) - } else { - let amount = sanitizedAddress.bolt11amount() ?? "0" + // Use the amount passed from the BIP21 parsing logic return (sanitizedAddress, amount, .isLightning) + } else { + let bolt11Amount = sanitizedAddress.bolt11amount() ?? amount + return (sanitizedAddress, bolt11Amount, .isLightning) } } diff --git a/LDKNodeMonday/Model/ReceiveOption.swift b/LDKNodeMonday/Model/ReceiveOption.swift index 68be748..9b1b7f8 100644 --- a/LDKNodeMonday/Model/ReceiveOption.swift +++ b/LDKNodeMonday/Model/ReceiveOption.swift @@ -10,7 +10,7 @@ import Foundation enum ReceiveOption: String, CaseIterable, Identifiable { var id: Self { self } - case bolt11JIT = "Bolt11 JIT" + case bolt11JIT = "BOLT11 JIT" case bip21 = "BIP21" } diff --git a/LDKNodeMonday/View Model/Home/Receive/AddressViewModel.swift b/LDKNodeMonday/View Model/Home/Receive/AddressViewModel.swift deleted file mode 100644 index 3c64ef0..0000000 --- a/LDKNodeMonday/View Model/Home/Receive/AddressViewModel.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// AddressViewModel.swift -// LDKNodeMonday -// -// Created by Matthew Ramsden on 5/29/23. -// - -import LDKNode -import SwiftUI - -class AddressViewModel: ObservableObject { - @Published var address: String = "" - @Published var addressViewError: MondayError? - @Published var networkColor = Color.gray - @Published var isAddressFinished: Bool = false - - func newFundingAddress() async { - do { - let address = try await LightningNodeService.shared.newAddress() - DispatchQueue.main.async { - self.address = address - self.isAddressFinished = true - } - } catch let error as NodeError { - let errorString = handleNodeError(error) - DispatchQueue.main.async { - self.addressViewError = .init(title: errorString.title, detail: errorString.detail) - } - } catch { - DispatchQueue.main.async { - self.addressViewError = .init( - title: "Unexpected error", - detail: error.localizedDescription - ) - } - } - } - - func getColor() { - let color = LightningNodeService.shared.networkColor - DispatchQueue.main.async { - self.networkColor = color - } - } - -} diff --git a/LDKNodeMonday/View Model/Home/AmountViewModel.swift b/LDKNodeMonday/View Model/Home/Send/AmountViewModel.swift similarity index 100% rename from LDKNodeMonday/View Model/Home/AmountViewModel.swift rename to LDKNodeMonday/View Model/Home/Send/AmountViewModel.swift diff --git a/LDKNodeMonday/View/Home/BitcoinView.swift b/LDKNodeMonday/View/Home/BitcoinView.swift index f51146d..c74e6f3 100644 --- a/LDKNodeMonday/View/Home/BitcoinView.swift +++ b/LDKNodeMonday/View/Home/BitcoinView.swift @@ -14,7 +14,7 @@ struct BitcoinView: View { @State private var isCopied = false @State private var showCheckmark = false @State private var showingBitcoinViewErrorAlert = false - @State private var isAddressSheetPresented = false + @State private var isReceiveSheetPresented = false @State private var isSendSheetPresented = false @State private var isPaymentsPresented = false @State private var showToast = false @@ -183,7 +183,7 @@ struct BitcoinView: View { .padding(.horizontal) Button { - isAddressSheetPresented = true + isReceiveSheetPresented = true } label: { HStack { Image(systemName: "arrow.down") @@ -293,7 +293,7 @@ struct BitcoinView: View { .font(.caption2) } .sheet( - isPresented: $isAddressSheetPresented, + isPresented: $isReceiveSheetPresented, onDismiss: { Task { await viewModel.getTotalOnchainBalanceSats() diff --git a/LDKNodeMonday/View/Home/Receive/AddressView.swift b/LDKNodeMonday/View/Home/Receive/AddressView.swift deleted file mode 100644 index 1db6a4c..0000000 --- a/LDKNodeMonday/View/Home/Receive/AddressView.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// AddressView.swift -// LDKNodeMonday -// -// Created by Matthew Ramsden on 2/20/23. -// - -import BitcoinUI -import SwiftUI - -struct AddressView: View { - @State private var isCopied = false - @State private var showCheckmark = false - @State private var showingAddressViewErrorAlert = false - @StateObject var viewModel: AddressViewModel - - var body: some View { - - VStack { - - if viewModel.address != "" { - QRCodeView(qrCodeType: .bitcoin(viewModel.address)) - .animation(.default, value: viewModel.address) - } else { - QRCodeView(qrCodeType: .lightning(viewModel.address)) - .blur(radius: 15) - } - - HStack(alignment: .center) { - - VStack(alignment: .leading, spacing: 5.0) { - if viewModel.isAddressFinished { - HStack { - Text("Bitcoin Network") - .font(.caption) - .bold() - } - Text(viewModel.address) - .font(.caption) - .truncationMode(.middle) - .lineLimit(1) - .foregroundColor(.secondary) - } else { - HStack { - Spacer() - ProgressView() - Spacer() - } - } - } - - Spacer() - - Button { - UIPasteboard.general.string = viewModel.address - isCopied = true - showCheckmark = true - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - isCopied = false - showCheckmark = false - } - } label: { - HStack { - withAnimation { - Image(systemName: showCheckmark ? "checkmark" : "doc.on.doc") - .font(.title2) - .minimumScaleFactor(0.5) - } - } - .bold() - } - - } - .padding() - - } - .tint(viewModel.networkColor) - .alert(isPresented: $showingAddressViewErrorAlert) { - Alert( - title: Text(viewModel.addressViewError?.title ?? "Unknown"), - message: Text(viewModel.addressViewError?.detail ?? ""), - dismissButton: .default(Text("OK")) { - viewModel.addressViewError = nil - } - ) - } - .onReceive(viewModel.$addressViewError) { errorMessage in - if errorMessage != nil { - showingAddressViewErrorAlert = true - } - } - .onAppear { - Task { - await viewModel.newFundingAddress() - viewModel.getColor() - } - } - - } - -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - AddressView(viewModel: .init()) - AddressView(viewModel: .init()) - .environment(\.sizeCategory, .accessibilityLarge) - AddressView(viewModel: .init()) - .environment(\.colorScheme, .dark) - } -} diff --git a/LDKNodeMonday/View/Home/Receive/BIP21View.swift b/LDKNodeMonday/View/Home/Receive/BIP21View.swift index 18c6186..4131bba 100644 --- a/LDKNodeMonday/View/Home/Receive/BIP21View.swift +++ b/LDKNodeMonday/View/Home/Receive/BIP21View.swift @@ -176,7 +176,7 @@ struct BIP21View: View { HStack(alignment: .center) { VStack(alignment: .leading, spacing: 5.0) { - Text("Bolt 11") + Text("BOLT 11") .bold() if let components = parseUnifiedQR(viewModel.unified) { Text(components.bolt11) @@ -225,7 +225,7 @@ struct BIP21View: View { HStack(alignment: .center) { VStack(alignment: .leading, spacing: 5.0) { - Text("Bolt 12") + Text("BOLT12") .bold() if let components = parseUnifiedQR(viewModel.unified) { Text(components.bolt12) diff --git a/LDKNodeMonday/View/Home/Receive/ReceiveView.swift b/LDKNodeMonday/View/Home/Receive/ReceiveView.swift index 113c7c1..fe7d759 100644 --- a/LDKNodeMonday/View/Home/Receive/ReceiveView.swift +++ b/LDKNodeMonday/View/Home/Receive/ReceiveView.swift @@ -14,7 +14,16 @@ struct ReceiveView: View { VStack { - CustomSegmentedPicker(options: ReceiveOption.allCases, selectedOption: $selectedOption) + Picker("Options", selection: $selectedOption) { + ForEach(ReceiveOption.allCases, id: \.self) { option in + HStack(spacing: 5) { + Image(systemName: option.systemImageName) + Text(option.rawValue) + } + .tag(option) + } + } + .pickerStyle(.menu) Spacer() @@ -30,39 +39,9 @@ struct ReceiveView: View { .padding(.vertical, 40.0) } -} - -struct CustomSegmentedPicker: View { - let options: [ReceiveOption] - @Binding var selectedOption: ReceiveOption - - var body: some View { - HStack { - ForEach(options, id: \.self) { option in - Button(action: { - self.selectedOption = option - }) { - VStack { - Image(systemName: option.systemImageName) - Text(option.rawValue) - } - .padding() - .font(.body) - .foregroundColor( - self.selectedOption == option ? Color.primary : Color.secondary - ) - - } - } - } - } } #Preview { ReceiveView() } - -#Preview { - CustomSegmentedPicker(options: ReceiveOption.allCases, selectedOption: .constant(.bip21)) -} diff --git a/LDKNodeMonday/View/Home/Send/AmountView.swift b/LDKNodeMonday/View/Home/Send/AmountView.swift index 49be1c2..3424c09 100644 --- a/LDKNodeMonday/View/Home/Send/AmountView.swift +++ b/LDKNodeMonday/View/Home/Send/AmountView.swift @@ -94,7 +94,7 @@ struct AmountView: View { // Need to figure out how to decode or add amount if address.starts(with: "lno") { // TODO: grab amount - Text("Bolt 12 Offer") + Text("BOLT12 Offer") .textStyle(BitcoinTitle1()) Text(address) .lineLimit(1)