diff --git a/Library/Coordinators/WalletCoordinator.swift b/Library/Coordinators/WalletCoordinator.swift index 0c59de517..dd1d02c10 100644 --- a/Library/Coordinators/WalletCoordinator.swift +++ b/Library/Coordinators/WalletCoordinator.swift @@ -103,9 +103,30 @@ 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: 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.Generic.Pasteboard.LightniningInvoiceFoundAlert.send, + style: .default) { _ in + self.presentSend(invoice: string) + } + alertController.addAction(cancelAlertAction) + alertController.addAction(sendPaymentAction) + (detailViewController ?? rootViewController).present(alertController, animated: true) + } private func presentUnlockWallet() { guard 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/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() } 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"; diff --git a/Lightning/Invoice/LightningInvoiceURI.swift b/Lightning/Invoice/LightningInvoiceURI.swift index 8edb44e52..70e0b4127 100644 --- a/Lightning/Invoice/LightningInvoiceURI.swift +++ b/Lightning/Invoice/LightningInvoiceURI.swift @@ -15,20 +15,14 @@ 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 @@ -39,4 +33,18 @@ public struct LightningInvoiceURI: PaymentURI { 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) + } }