From 391e54942173eadfc44ef6dc863948e2b701e834 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Tue, 27 Jun 2023 23:59:37 +0200 Subject: [PATCH] feat: responsible new stream modal --- package.json | 1 + src/element/modal.css | 4 +- src/element/modal.tsx | 2 +- src/element/new-stream.css | 22 +++- src/element/new-stream.tsx | 75 +++++++++--- src/element/send-zap.tsx | 226 ++++++++++++++++++++++--------------- src/pages/layout.tsx | 20 +--- src/pages/stream-page.tsx | 52 +++------ yarn.lock | 218 ++++++++++++++++++++++++++++++++++- 9 files changed, 451 insertions(+), 169 deletions(-) diff --git a/package.json b/package.json index 54f00a2..7abebc3 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@radix-ui/react-dialog": "^1.0.4", "@react-hook/resize-observer": "^1.2.6", "@snort/system-react": "^1.0.8", "@testing-library/jest-dom": "^5.14.1", diff --git a/src/element/modal.css b/src/element/modal.css index b8181bf..d49c6cb 100644 --- a/src/element/modal.css +++ b/src/element/modal.css @@ -13,10 +13,10 @@ .modal-body { display: flex; - width: 430px; + max-width: 430px; padding: 32px; margin-top: auto; margin-bottom: auto; border-radius: 32px; background: #171717; -} \ No newline at end of file +} diff --git a/src/element/modal.tsx b/src/element/modal.tsx index 8f7f7ca..f7345ad 100644 --- a/src/element/modal.tsx +++ b/src/element/modal.tsx @@ -18,7 +18,7 @@ export default function Modal(props: ModalProps) { return (
-
e.stopPropagation()}> +
e.stopPropagation()}> {props.children}
diff --git a/src/element/new-stream.css b/src/element/new-stream.css index e05814b..629fd25 100644 --- a/src/element/new-stream.css +++ b/src/element/new-stream.css @@ -2,7 +2,6 @@ display: flex; flex-direction: column; gap: 24px; - width: inherit; } .new-stream h3 { @@ -49,4 +48,23 @@ .new-stream .pill.active { color: inherit; background: #353535; -} \ No newline at end of file +} + +.dialog-overlay { + background-color: rgba(0, 0, 0, 0.8); + position: fixed; + inset: 0; +} + +.dialog-content { + background-color: #171717; + border-radius: 6px; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 90vw; + max-width: 450px; + max-height: 85vh; + padding: 25px; +} diff --git a/src/element/new-stream.tsx b/src/element/new-stream.tsx index 68f6fd8..6ef9bfc 100644 --- a/src/element/new-stream.tsx +++ b/src/element/new-stream.tsx @@ -1,4 +1,5 @@ import "./new-stream.css"; +import * as Dialog from "@radix-ui/react-dialog"; import { useEffect, useState } from "react"; import { EventPublisher, NostrEvent } from "@snort/system"; @@ -6,6 +7,7 @@ import { unixNow } from "@snort/shared"; import AsyncButton from "./async-button"; import { StreamState, System } from "index"; +import { Icon } from "element/icon"; import { findTag } from "utils"; export function NewStream({ @@ -19,7 +21,9 @@ export function NewStream({ const [summary, setSummary] = useState(findTag(ev, "summary") ?? ""); const [image, setImage] = useState(findTag(ev, "image") ?? ""); const [stream, setStream] = useState(findTag(ev, "streaming") ?? ""); - const [status, setStatus] = useState(findTag(ev, "status") ?? StreamState.Live); + const [status, setStatus] = useState( + findTag(ev, "status") ?? StreamState.Live + ); const [start, setStart] = useState(findTag(ev, "starts")); const [isValid, setIsValid] = useState(false); @@ -48,8 +52,7 @@ export function NewStream({ const dTag = findTag(ev, "d") ?? now.toString(); const starts = start ?? now.toString(); const ends = findTag(ev, "ends") ?? now.toString(); - eb - .kind(30_311) + eb.kind(30_311) .tag(["d", dTag]) .tag(["title", title]) .tag(["summary", summary]) @@ -69,11 +72,11 @@ export function NewStream({ } function toDateTimeString(n: number) { - return new Date(n * 1000).toISOString().substring(0, -1) + return new Date(n * 1000).toISOString().substring(0, -1); } function fromDateTimeString(s: string) { - return Math.floor(new Date(s).getTime() / 1000) + return Math.floor(new Date(s).getTime() / 1000); } return ( @@ -127,17 +130,32 @@ export function NewStream({

Status

- {[StreamState.Live, StreamState.Planned, StreamState.Ended].map(v => setStatus(v)}> - {v} - )} + {[StreamState.Live, StreamState.Planned, StreamState.Ended].map( + (v) => ( + setStatus(v)} + > + {v} + + ) + )}
- {status === StreamState.Planned &&
-

Start Time

-
- setStart(fromDateTimeString(e.target.value).toString())} /> + {status === StreamState.Planned && ( +
+

Start Time

+
+ + setStart(fromDateTimeString(e.target.value).toString()) + } + /> +
-
} + )}
); } + +interface NewStreamDialogProps { + text?: string; + btnClassName?: string; + ev?: NostrEvent; + onFinish: (e: NostrEvent) => void; +} + +export function NewStreamDialog({ + text = "New Stream", + ev, + onFinish, + btnClassName = "btn", +}: NewStreamDialogProps) { + return ( + + + + + + + + + + + + ); +} diff --git a/src/element/send-zap.tsx b/src/element/send-zap.tsx index 343f890..87b8de8 100644 --- a/src/element/send-zap.tsx +++ b/src/element/send-zap.tsx @@ -9,107 +9,149 @@ import { findTag } from "utils"; import { Relays } from "index"; import QrCode from "./qr-code"; -export function SendZaps({ lnurl, ev, targetName, onFinish }: { lnurl: string, ev?: NostrEvent, targetName?: string, onFinish: () => void }) { - const UsdRate = 30_000; +export function SendZaps({ + lnurl, + ev, + targetName, + onFinish, +}: { + lnurl: string; + ev?: NostrEvent; + targetName?: string; + onFinish: () => void; +}) { + const UsdRate = 30_000; - const satsAmounts = [ - 100, 1_000, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000 - ]; - const usdAmounts = [ - 0.05, 0.50, 2, 5, 10, 50, 100, 200 - ] - const [isFiat, setIsFiat] = useState(false); - const [svc, setSvc] = useState(); - const [amount, setAmount] = useState(satsAmounts[0]); - const [comment, setComment] = useState(""); - const [invoice, setInvoice] = useState(""); + const satsAmounts = [ + 100, 1_000, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000, + ]; + const usdAmounts = [0.05, 0.5, 2, 5, 10, 50, 100, 200]; + const [isFiat, setIsFiat] = useState(false); + const [svc, setSvc] = useState(); + const [amount, setAmount] = useState(satsAmounts[0]); + const [comment, setComment] = useState(""); + const [invoice, setInvoice] = useState(""); - const name = targetName ?? svc?.name; - async function loadService() { - const s = new LNURL(lnurl); - await s.load(); - setSvc(s); + const name = targetName ?? svc?.name; + async function loadService() { + const s = new LNURL(lnurl); + await s.load(); + setSvc(s); + } + + useEffect(() => { + if (!svc) { + loadService().catch(console.warn); } + }, [lnurl]); - useEffect(() => { - if (!svc) { - loadService().catch(console.warn); - } - }, [lnurl]); - - async function send() { - if (!svc) return; - const pub = await EventPublisher.nip7(); - if (!pub) return; - - const amountInSats = isFiat ? Math.floor((amount / UsdRate) * 1e8) : amount; - let zap: NostrEvent | undefined; - if (ev) { - zap = await pub.zap(amountInSats * 1000, ev.pubkey, Relays, undefined, comment, eb => { - return eb.tag(["a", `${ev.kind}:${ev.pubkey}:${findTag(ev, "d")}`]); - }); - } - const invoice = await svc.getInvoice(amountInSats, comment, zap); - if (!invoice.pr) return; - - if (window.webln) { - await window.webln.enable(); - await window.webln.sendPayment(invoice.pr); - onFinish(); - } else { - setInvoice(invoice.pr); + async function send() { + if (!svc) return; + const pub = await EventPublisher.nip7(); + if (!pub) return; + + const amountInSats = isFiat ? Math.floor((amount / UsdRate) * 1e8) : amount; + let zap: NostrEvent | undefined; + if (ev) { + zap = await pub.zap( + amountInSats * 1000, + ev.pubkey, + Relays, + undefined, + comment, + (eb) => { + return eb.tag(["a", `${ev.kind}:${ev.pubkey}:${findTag(ev, "d")}`]); } + ); } + const invoice = await svc.getInvoice(amountInSats, comment, zap); + if (!invoice.pr) return; - function input() { - if (invoice) return; - return <> -
- { setIsFiat(false); setAmount(satsAmounts[0]) }}> - SATS - - { setIsFiat(true); setAmount(usdAmounts[0]) }}> - USD - -
-
- Zap amount in {isFiat ? "USD" : "sats"} -
- {(isFiat ? usdAmounts : satsAmounts).map(a => - setAmount(a)}> - {isFiat ? `$${a.toLocaleString()}` : formatSats(a)} - )} -
-
-
- - Your comment for {name} - -
-