Custom amounts on LNURL
This commit is contained in:
parent
037f39e386
commit
18b6f19894
@ -2,7 +2,7 @@
|
|||||||
background-color: #222;
|
background-color: #222;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 50vw;
|
width: 500px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
min-height: 10vh;
|
min-height: 10vh;
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,23 @@ export default function LNURLTip(props) {
|
|||||||
const amounts = [50, 100, 500, 1_000, 5_000, 10_000];
|
const amounts = [50, 100, 500, 1_000, 5_000, 10_000];
|
||||||
const [payService, setPayService] = useState("");
|
const [payService, setPayService] = useState("");
|
||||||
const [amount, setAmount] = useState(0);
|
const [amount, setAmount] = useState(0);
|
||||||
|
const [customAmount, setCustomAmount] = useState(0);
|
||||||
const [invoice, setInvoice] = useState("");
|
const [invoice, setInvoice] = useState("");
|
||||||
const [comment, setComment] = useState("");
|
const [comment, setComment] = useState("");
|
||||||
const [error, setError] = useState("")
|
const [error, setError] = useState("")
|
||||||
|
|
||||||
|
const selectAmount = (a) => {
|
||||||
|
setError("");
|
||||||
|
setInvoice("");
|
||||||
|
setAmount(a);
|
||||||
|
};
|
||||||
|
|
||||||
async function fetchJson(url) {
|
async function fetchJson(url) {
|
||||||
let rsp = await fetch(url);
|
let rsp = await fetch(url);
|
||||||
if (rsp.ok) {
|
if (rsp.ok) {
|
||||||
let data = await rsp.json();
|
let data = await rsp.json();
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
setError("");
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -48,6 +56,7 @@ export default function LNURLTip(props) {
|
|||||||
setError(data.reason);
|
setError(data.reason);
|
||||||
} else {
|
} else {
|
||||||
setInvoice(data.pr);
|
setInvoice(data.pr);
|
||||||
|
setError("");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setError("Failed to load invoice");
|
setError("Failed to load invoice");
|
||||||
@ -57,6 +66,17 @@ export default function LNURLTip(props) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function custom() {
|
||||||
|
let min = (payService?.minSendable ?? 0) / 1000;
|
||||||
|
let max = (payService?.maxSendable ?? 21_000_000_000) / 1000;
|
||||||
|
return (
|
||||||
|
<div className="flex mb10">
|
||||||
|
<input type="number" min={min} max={max} className="f-grow mr10" value={customAmount} onChange={(e) => setCustomAmount(e.target.value)} />
|
||||||
|
<div className="btn" onClick={() => selectAmount(customAmount)}>Confirm</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (payService && amount > 0) {
|
if (payService && amount > 0) {
|
||||||
loadInvoice();
|
loadInvoice();
|
||||||
@ -83,8 +103,11 @@ export default function LNURLTip(props) {
|
|||||||
const metadata = useMemo(() => {
|
const metadata = useMemo(() => {
|
||||||
if (payService) {
|
if (payService) {
|
||||||
let meta = JSON.parse(payService.metadata);
|
let meta = JSON.parse(payService.metadata);
|
||||||
|
let desc = meta.find(a => a[0] === "text/plain");
|
||||||
|
let image = meta.find(a => a[0] === "image/png;base64");
|
||||||
return {
|
return {
|
||||||
description: meta.find(a => a[0] === "text/plain")[1]
|
description: desc ? desc[1] : null,
|
||||||
|
image: image ? image[1] : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -95,17 +118,21 @@ export default function LNURLTip(props) {
|
|||||||
<Modal onClose={() => onClose()}>
|
<Modal onClose={() => onClose()}>
|
||||||
<div className="lnurl-tip" onClick={(e) => e.stopPropagation()}>
|
<div className="lnurl-tip" onClick={(e) => e.stopPropagation()}>
|
||||||
<h2>⚡️ Send sats</h2>
|
<h2>⚡️ Send sats</h2>
|
||||||
<div className="f-ellipsis mb10">{service}</div>
|
<div className="f-ellipsis mb10">{metadata?.description ?? service}</div>
|
||||||
<div className="f-ellipsis mb10">{metadata?.description}</div>
|
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
{payService?.commentAllowed > 0 ?
|
{payService?.commentAllowed > 0 ?
|
||||||
<input type="text" placeholder="Comment" className="mb10 f-grow" maxLength={payService?.commentAllowed} onChange={(e) => setComment(e.target.value)} /> : null}
|
<input type="text" placeholder="Comment" className="mb10 f-grow" maxLength={payService?.commentAllowed} onChange={(e) => setComment(e.target.value)} /> : null}
|
||||||
</div>
|
</div>
|
||||||
<div className="mb10">
|
<div className="mb10">
|
||||||
{serviceAmounts.map(a => <span className={`pill ${amount === a ? "active" : ""}`} key={a} onClick={() => setAmount(a)}>
|
{serviceAmounts.map(a => <span className={`pill ${amount === a ? "active" : ""}`} key={a} onClick={() => selectAmount(a)}>
|
||||||
{a.toLocaleString()}
|
{a.toLocaleString()}
|
||||||
</span>)}
|
</span>)}
|
||||||
|
{payService ?
|
||||||
|
<span className={`pill ${amount === -1 ? "active" : ""}`} onClick={() => selectAmount(-1)}>
|
||||||
|
Custom
|
||||||
|
</span> : null}
|
||||||
</div>
|
</div>
|
||||||
|
{amount === -1 ? custom() : null}
|
||||||
{error ? <p className="error">{error}</p> : null}
|
{error ? <p className="error">{error}</p> : null}
|
||||||
<QrCode link={invoice} />
|
<QrCode link={invoice} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -24,7 +24,7 @@ export default function Note(props) {
|
|||||||
const emojiReactions = reactions?.filter(({ Content }) => Content && Content !== "+" && Content !== "-" && Content !== "❤️")
|
const emojiReactions = reactions?.filter(({ Content }) => Content && Content !== "+" && Content !== "-" && Content !== "❤️")
|
||||||
.reduce((acc, { Content }) => {
|
.reduce((acc, { Content }) => {
|
||||||
const amount = acc[Content] || 0
|
const amount = acc[Content] || 0
|
||||||
return {...acc, [Content]: amount + 1 }
|
return { ...acc, [Content]: amount + 1 }
|
||||||
}, {})
|
}, {})
|
||||||
const likes = reactions?.filter(({ Content }) => Content === "+" || Content === "❤️").length ?? 0
|
const likes = reactions?.filter(({ Content }) => Content === "+" || Content === "❤️").length ?? 0
|
||||||
const dislikes = reactions?.filter(({ Content }) => Content === "-").length ?? 0
|
const dislikes = reactions?.filter(({ Content }) => Content === "-").length ?? 0
|
||||||
|
@ -32,6 +32,8 @@ export default function QrCode(props) {
|
|||||||
elm.href = `lightning:${link}`;
|
elm.href = `lightning:${link}`;
|
||||||
elm.click();
|
elm.click();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
qrRef.current.innerHTML = "";
|
||||||
}
|
}
|
||||||
}, [link]);
|
}, [link]);
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ code {
|
|||||||
border-radius: 25px;
|
border-radius: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"], input[type="password"], textarea {
|
input[type="text"], input[type="password"], input[type="number"], textarea {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 0;
|
border: 0;
|
||||||
@ -120,6 +120,7 @@ span.pill {
|
|||||||
|
|
||||||
span.pill.active {
|
span.pill.active {
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.pill:hover {
|
span.pill:hover {
|
||||||
|
Loading…
Reference in New Issue
Block a user