From 1f40f5643e1604924fa28dcff1c42a5cdea83fb4 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 24 Mar 2023 11:04:40 -0500 Subject: [PATCH] add lightning payment mode setting --- .changeset/yellow-trainers-sparkle.md | 5 +++ src/components/zap-modal.tsx | 49 ++++++++++++++++++++------- src/services/settings.ts | 7 ++++ src/views/settings/index.tsx | 42 +++++++++++++++++++++-- 4 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 .changeset/yellow-trainers-sparkle.md diff --git a/.changeset/yellow-trainers-sparkle.md b/.changeset/yellow-trainers-sparkle.md new file mode 100644 index 000000000..0d5d2f751 --- /dev/null +++ b/.changeset/yellow-trainers-sparkle.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Add lighting payment mode setting diff --git a/src/components/zap-modal.tsx b/src/components/zap-modal.tsx index fd348bf6c..c05eec722 100644 --- a/src/components/zap-modal.tsx +++ b/src/components/zap-modal.tsx @@ -1,6 +1,7 @@ import { Button, ButtonGroup, + DefaultIcon, Flex, IconButton, Input, @@ -33,6 +34,7 @@ import { useSigningContext } from "../providers/signing-provider"; import QrCodeSvg from "./qr-code-svg"; import { CopyIconButton } from "./copy-icon-button"; import { useIsMobile } from "../hooks/use-is-mobile"; +import settings from "../services/settings"; type FormValues = { amount: number; @@ -59,7 +61,7 @@ export default function ZapModal({ const metadata = useUserMetadata(pubkey); const { requestSignature } = useSigningContext(); const toast = useToast(); - const [invoice, setInvoice] = useState(); + const [promptInvoice, setPromptInvoice] = useState(); const { isOpen: showQr, onToggle: toggleQr } = useDisclosure(); const isMobile = useIsMobile(); @@ -118,7 +120,7 @@ export default function ZapModal({ const parsed = parsePaymentRequest(payRequest); if (parsed.amount !== amountInMilisat) throw new Error("incorrect amount"); - setInvoice(payRequest); + payInvoice(payRequest); } else throw new Error("Failed to get invoice"); } } else { @@ -131,7 +133,7 @@ export default function ZapModal({ const parsed = parsePaymentRequest(payRequest); if (parsed.amount !== amountInMilisat) throw new Error("incorrect amount"); - setInvoice(payRequest); + payInvoice(payRequest); } else throw new Error("Failed to get invoice"); } } else throw new Error("Failed to get LNURL metadata"); @@ -140,7 +142,7 @@ export default function ZapModal({ } }; - const payWithWebLn = async () => { + const payWithWebLn = async (invoice: string) => { if (window.webln && invoice) { if (!window.webln.enabled) await window.webln.enable(); await window.webln.sendPayment(invoice); @@ -155,7 +157,7 @@ export default function ZapModal({ onClose(); } }; - const payWithApp = async () => { + const payWithApp = async (invoice: string) => { window.open("lightning:" + invoice); const listener = () => { @@ -170,9 +172,24 @@ export default function ZapModal({ }, 1000 * 2); }; + const payInvoice = (invoice: string) => { + switch (settings.lightningPayMode.value) { + case "webln": + payWithWebLn(invoice); + break; + case "external": + payWithApp(invoice); + break; + default: + case "prompt": + setPromptInvoice(invoice); + break; + } + }; + const handleClose = () => { - // if there was an invoice and we a closing the modal. presume it was paid - if (invoice && onPaid) { + // if there was an invoice and we are closing the modal. presume it was paid + if (promptInvoice && onPaid) { onPaid(); } onClose(); @@ -183,11 +200,11 @@ export default function ZapModal({ - {invoice ? ( + {promptInvoice ? ( - {showQr && } + {showQr && } - + } aria-label="Show QrCode" @@ -195,15 +212,21 @@ export default function ZapModal({ variant="solid" size="md" /> - + {window.webln && ( - )} - diff --git a/src/services/settings.ts b/src/services/settings.ts index 9b293859a..f826df3de 100644 --- a/src/services/settings.ts +++ b/src/services/settings.ts @@ -2,6 +2,12 @@ import { PersistentSubject } from "../classes/subject"; import db from "./db"; import { Account } from "./account"; +export enum LightningPayMode { + Prompt = "prompt", + Webln = "webln", + External = "external", +} + const settings = { blurImages: new PersistentSubject(true), autoShowMedia: new PersistentSubject(true), @@ -9,6 +15,7 @@ const settings = { showReactions: new PersistentSubject(true), showSignatureVerification: new PersistentSubject(false), accounts: new PersistentSubject([]), + lightningPayMode: new PersistentSubject(LightningPayMode.Prompt), }; async function loadSettings() { diff --git a/src/views/settings/index.tsx b/src/views/settings/index.tsx index 95884c479..8225fc300 100644 --- a/src/views/settings/index.tsx +++ b/src/views/settings/index.tsx @@ -13,13 +13,14 @@ import { AccordionIcon, ButtonGroup, FormHelperText, + Select, } from "@chakra-ui/react"; import { useState } from "react"; -import settings from "../../services/settings"; +import settings, { LightningPayMode } from "../../services/settings"; import { clearCacheData, deleteDatabase } from "../../services/db"; import accountService from "../../services/account"; import useSubject from "../../hooks/use-subject"; -import { LogoutIcon } from "../../components/icons"; +import { LightningIcon, LogoutIcon } from "../../components/icons"; export default function SettingsView() { const blurImages = useSubject(settings.blurImages); @@ -27,6 +28,7 @@ export default function SettingsView() { const proxyUserMedia = useSubject(settings.proxyUserMedia); const showReactions = useSubject(settings.showReactions); const showSignatureVerification = useSubject(settings.showSignatureVerification); + const lightningPayMode = useSubject(settings.lightningPayMode); const { colorMode, setColorMode } = useColorMode(); @@ -178,6 +180,42 @@ export default function SettingsView() { + +

+ + + Lightning + + + +

+ + + + + Payment mode + + + + Prompt: Ask every time +
+ WebLN: Use browser extension +
+ External: Open an external app using "lightning:" link +
+
+
+
+
+