From 4936a6c57c8f79b4cb5308100394e22347f4cb3e Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 10:10:41 -0800 Subject: [PATCH 1/6] If a lightning invoice is detected in the pasteboard, invoke `presentSend` --- Library/Coordinators/WalletCoordinator.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Library/Coordinators/WalletCoordinator.swift b/Library/Coordinators/WalletCoordinator.swift index 0c59de517..a1947966b 100644 --- a/Library/Coordinators/WalletCoordinator.swift +++ b/Library/Coordinators/WalletCoordinator.swift @@ -95,6 +95,14 @@ final class WalletCoordinator: NSObject, Coordinator { case .running, .syncing: if currentState != .syncing && currentState != .running { presentMain() + } else { + let pasteboard = UIPasteboard.general + if let string = pasteboard.string { + if let lightningInvoice = LightningInvoiceURI(string: string) { + Logger.verbose(lightningInvoice.uriString) + presentSend(invoice: string) + } + } } case .locked: presentUnlockWallet() From 7d3c41672555b6d34df58555b8411c28ba9b67fd Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 11:37:42 -0800 Subject: [PATCH 2/6] Add method `validate` in LightningInvoiceURI --- Lightning/Invoice/LightningInvoiceURI.swift | 32 +++++++++++++-------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Lightning/Invoice/LightningInvoiceURI.swift b/Lightning/Invoice/LightningInvoiceURI.swift index 8edb44e52..d6ab5fe87 100644 --- a/Lightning/Invoice/LightningInvoiceURI.swift +++ b/Lightning/Invoice/LightningInvoiceURI.swift @@ -15,28 +15,36 @@ public struct LightningInvoiceURI: PaymentURI { public let address: String public let network: Network public var isCaseSensitive = false - + private static let lightningPrefix = "lightning:" + public var uriString: String { return "lightning:\(address)" } - + public init?(string: String) { - var string = string.lowercased() - - let prefix = "lightning:" - if string.starts(with: prefix) { - string = String(string.dropFirst(prefix.count)) - } - - guard let invoice = Bolt11.decode(string: string) else { return nil } - + guard let invoice = LightningInvoiceURI.decode(string: string) else { return nil } + address = string amount = invoice.amount memo = invoice.description network = invoice.network } - + public init?(invoice: Invoice) { self.init(string: invoice.paymentRequest) } + + public static func validate(string: String) -> Bool { + return decode(string: string) != nil + } + + private static func decode(string: String) -> Bolt11.Invoice? { + var string = string.lowercased() + + if string.starts(with: lightningPrefix) { + string = String(string.dropFirst(lightningPrefix.count)) + } + + return Bolt11.decode(string: string) + } } From 53fe1928383278ed9dabbe695143031577f2c0b9 Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 11:39:21 -0800 Subject: [PATCH 3/6] Fix a typo BTW --- Library/Scenes/ManageWallets/WalletConfigurationStore.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Scenes/ManageWallets/WalletConfigurationStore.swift b/Library/Scenes/ManageWallets/WalletConfigurationStore.swift index bb25510a2..83f233511 100644 --- a/Library/Scenes/ManageWallets/WalletConfigurationStore.swift +++ b/Library/Scenes/ManageWallets/WalletConfigurationStore.swift @@ -37,7 +37,7 @@ final class WalletConfigurationStore { return configurations.isEmpty } private(set) var configurations: [WalletConfiguration] - var selectedWallet: WalletConfiguration? { // make lighting connection + var selectedWallet: WalletConfiguration? { // make lightning connection didSet { save() } From 22045288049b7a6e3265ca6e69f72058d46664c2 Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 11:45:52 -0800 Subject: [PATCH 4/6] Ask the user if they want to send payment via Alert Controller --- Library/Coordinators/WalletCoordinator.swift | 30 +++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Library/Coordinators/WalletCoordinator.swift b/Library/Coordinators/WalletCoordinator.swift index a1947966b..f0dc150dd 100644 --- a/Library/Coordinators/WalletCoordinator.swift +++ b/Library/Coordinators/WalletCoordinator.swift @@ -95,14 +95,6 @@ final class WalletCoordinator: NSObject, Coordinator { case .running, .syncing: if currentState != .syncing && currentState != .running { presentMain() - } else { - let pasteboard = UIPasteboard.general - if let string = pasteboard.string { - if let lightningInvoice = LightningInvoiceURI(string: string) { - Logger.verbose(lightningInvoice.uriString) - presentSend(invoice: string) - } - } } case .locked: presentUnlockWallet() @@ -111,22 +103,40 @@ final class WalletCoordinator: NSObject, Coordinator { } self.currentState = state + if self.currentState == .syncing || self.currentState == .running { + detectPasteboardForLightningInvoice() + } UIApplication.shared.isIdleTimerDisabled = lightningService.connection == .local && state == .syncing } + + private func detectPasteboardForLightningInvoice() { + let pasteboard = UIPasteboard.general + guard let string = pasteboard.string else { return } + guard LightningInvoiceURI.validate(string: string) else { return } + + let alertController = UIAlertController(title: "Lightning Invoice found in clipboard", message: "Would you like to send payment for the invoice?", preferredStyle: .actionSheet) + let cancelAlertAction = UIAlertAction(title: L10n.Generic.cancel, style: .cancel, handler: nil) + let sendPaymentAction = UIAlertAction(title: L10n.Scene.Send.sendButton, style: .default) { _ in + self.presentSend(invoice: string) + } + alertController.addAction(cancelAlertAction) + alertController.addAction(sendPaymentAction) + (detailViewController ?? rootViewController).present(alertController, animated: true) + } private func presentUnlockWallet() { guard case .remote(let rpcConfiguration) = lightningService.connection, // we can only unlock remote nodes let disconnectWalletDelegate = disconnectWalletDelegate else { return } - + let unlockWalletViewModel = UnlockWalletViewModel(lightningService: lightningService, alias: rpcConfiguration.host.absoluteString) let viewController = UnlockWalletViewController.instantiate(unlockWalletViewModel: unlockWalletViewModel, disconnectWalletDelegate: disconnectWalletDelegate) let navigationController = ZapNavigationController(rootViewController: viewController) presentViewController(navigationController) } - + private func presentLoading() { let viewController = LoadingViewController.instantiate() presentViewController(viewController) From 518c046648ed70ab4e8063fa87c3b5c5b6ea5d53 Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 12:32:48 -0800 Subject: [PATCH 5/6] Move alert related strings into `Localizable.strings` --- Library/Coordinators/WalletCoordinator.swift | 7 +++++-- Library/Generated/strings.swift | 8 ++++++++ Library/en.lproj/Localizable.strings | 3 +++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Library/Coordinators/WalletCoordinator.swift b/Library/Coordinators/WalletCoordinator.swift index f0dc150dd..df958eba2 100644 --- a/Library/Coordinators/WalletCoordinator.swift +++ b/Library/Coordinators/WalletCoordinator.swift @@ -115,9 +115,12 @@ final class WalletCoordinator: NSObject, Coordinator { guard let string = pasteboard.string else { return } guard LightningInvoiceURI.validate(string: string) else { return } - let alertController = UIAlertController(title: "Lightning Invoice found in clipboard", message: "Would you like to send payment for the invoice?", preferredStyle: .actionSheet) + let alertController = UIAlertController(title: L10n.Generic.Pasteboard.LightniningInvoiceFoundAlert.title, + message: L10n.Generic.Pasteboard.LightniningInvoiceFoundAlert.message, + preferredStyle: .actionSheet) let cancelAlertAction = UIAlertAction(title: L10n.Generic.cancel, style: .cancel, handler: nil) - let sendPaymentAction = UIAlertAction(title: L10n.Scene.Send.sendButton, style: .default) { _ in + let sendPaymentAction = UIAlertAction(title: L10n.Generic.Pasteboard.LightniningInvoiceFoundAlert.send, + style: .default) { _ in self.presentSend(invoice: string) } alertController.addAction(cancelAlertAction) diff --git a/Library/Generated/strings.swift b/Library/Generated/strings.swift index 1e65f3ccf..6c3676e51 100644 --- a/Library/Generated/strings.swift +++ b/Library/Generated/strings.swift @@ -75,6 +75,14 @@ internal enum L10n { internal enum Pasteboard { /// Invalid Address internal static let invalidAddress = L10n.tr("Localizable", "generic.pasteboard.invalid_address") + internal enum LightniningInvoiceFoundAlert { + /// Would you like to send a payment for the invoice? + internal static let message = L10n.tr("Localizable", "generic.pasteboard.lightnining_invoice_found_alert.message") + /// Send + internal static let send = L10n.tr("Localizable", "generic.pasteboard.lightnining_invoice_found_alert.send") + /// Lightning Invoice found on clipboard + internal static let title = L10n.tr("Localizable", "generic.pasteboard.lightnining_invoice_found_alert.title") + } } internal enum QrCode { /// Copy diff --git a/Library/en.lproj/Localizable.strings b/Library/en.lproj/Localizable.strings index bb353538a..df90e049f 100644 --- a/Library/en.lproj/Localizable.strings +++ b/Library/en.lproj/Localizable.strings @@ -2,6 +2,9 @@ "generic.qr_code.copy_button" = "Copy"; "generic.qr_code.copy_success_message" = "Address has been copied to clipboard."; "generic.pasteboard.invalid_address" = "Invalid Address"; +"generic.pasteboard.lightnining_invoice_found_alert.send" = "Send"; +"generic.pasteboard.lightnining_invoice_found_alert.title" = "Lightning Invoice found on clipboard"; +"generic.pasteboard.lightnining_invoice_found_alert.message" = "Would you like to send a payment for the invoice?"; "generic.qr_code.share_button" = "Share"; "generic.cancel" = "Cancel"; From 1e47267fe7fc96e9a2a801a5989b456149940500 Mon Sep 17 00:00:00 2001 From: FreeThinker Date: Tue, 31 Dec 2019 12:34:56 -0800 Subject: [PATCH 6/6] Remove trailing spaces --- Library/Coordinators/WalletCoordinator.swift | 4 ++-- Lightning/Invoice/LightningInvoiceURI.swift | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Library/Coordinators/WalletCoordinator.swift b/Library/Coordinators/WalletCoordinator.swift index df958eba2..dd1d02c10 100644 --- a/Library/Coordinators/WalletCoordinator.swift +++ b/Library/Coordinators/WalletCoordinator.swift @@ -133,13 +133,13 @@ final class WalletCoordinator: NSObject, Coordinator { case .remote(let rpcConfiguration) = lightningService.connection, // we can only unlock remote nodes let disconnectWalletDelegate = disconnectWalletDelegate else { return } - + let unlockWalletViewModel = UnlockWalletViewModel(lightningService: lightningService, alias: rpcConfiguration.host.absoluteString) let viewController = UnlockWalletViewController.instantiate(unlockWalletViewModel: unlockWalletViewModel, disconnectWalletDelegate: disconnectWalletDelegate) let navigationController = ZapNavigationController(rootViewController: viewController) presentViewController(navigationController) } - + private func presentLoading() { let viewController = LoadingViewController.instantiate() presentViewController(viewController) diff --git a/Lightning/Invoice/LightningInvoiceURI.swift b/Lightning/Invoice/LightningInvoiceURI.swift index d6ab5fe87..70e0b4127 100644 --- a/Lightning/Invoice/LightningInvoiceURI.swift +++ b/Lightning/Invoice/LightningInvoiceURI.swift @@ -16,35 +16,35 @@ public struct LightningInvoiceURI: PaymentURI { public let network: Network public var isCaseSensitive = false private static let lightningPrefix = "lightning:" - + public var uriString: String { return "lightning:\(address)" } - + public init?(string: String) { guard let invoice = LightningInvoiceURI.decode(string: string) else { return nil } - + address = string amount = invoice.amount memo = invoice.description network = invoice.network } - + public init?(invoice: Invoice) { self.init(string: invoice.paymentRequest) } - + public static func validate(string: String) -> Bool { return decode(string: string) != nil } - + private static func decode(string: String) -> Bolt11.Invoice? { var string = string.lowercased() - + if string.starts(with: lightningPrefix) { string = String(string.dropFirst(lightningPrefix.count)) } - + return Bolt11.decode(string: string) } }