From 01348a1d9f0cf804a071858067124a3eb4260cd3 Mon Sep 17 00:00:00 2001 From: Alejandro Gomez Date: Tue, 7 Feb 2023 11:38:34 +0100 Subject: [PATCH] Zap modal --- src/Element/AsyncButton.tsx | 6 +- src/Element/Invoice.tsx | 2 +- src/Element/LNURLTip.css | 134 ++++++++++++++++++++++++++--- src/Element/LNURLTip.tsx | 162 +++++++++++++++++++++++++----------- src/Element/NoteCreator.css | 1 + src/Element/NoteFooter.tsx | 9 +- src/Element/Tabs.css | 4 +- src/Element/Zap.css | 6 +- src/Element/ZapButton.tsx | 2 +- src/Icons/Close.tsx | 11 +++ src/Icons/Reply.tsx | 8 +- src/Pages/ProfilePage.tsx | 8 +- src/index.css | 50 ++++++----- 13 files changed, 305 insertions(+), 98 deletions(-) create mode 100644 src/Icons/Close.tsx diff --git a/src/Element/AsyncButton.tsx b/src/Element/AsyncButton.tsx index 0c12851d..784d9ea7 100644 --- a/src/Element/AsyncButton.tsx +++ b/src/Element/AsyncButton.tsx @@ -20,8 +20,8 @@ export default function AsyncButton(props: any) { } return ( -
handle(e)}> - {props.children} -
+ ) } \ No newline at end of file diff --git a/src/Element/Invoice.tsx b/src/Element/Invoice.tsx index 0bba9364..1d7dc2d9 100644 --- a/src/Element/Invoice.tsx +++ b/src/Element/Invoice.tsx @@ -49,7 +49,7 @@ export default function Invoice(props: InvoiceProps) { <>

Lightning Invoice

- setShowInvoice(false)} /> + setShowInvoice(false)} /> ) } diff --git a/src/Element/LNURLTip.css b/src/Element/LNURLTip.css index 20fb44ab..14b480aa 100644 --- a/src/Element/LNURLTip.css +++ b/src/Element/LNURLTip.css @@ -1,5 +1,58 @@ +.lnurl-modal .lnurl-tip .pfp .avatar { + width: 48px; + height: 48px; +} + +.lnurl-modal .modal-body { + padding: 0; + max-width: 470px; +} + .lnurl-tip { - text-align: center; + padding: 24px 32px; + background-color: #1B1B1B; + border-radius: 16px; + position: relative; +} + +.light .lnurl-tip { + background-color: var(--note-bg); +} + +.lnurl-tip h3 { + color: var(--font-secondary-color); + font-size: 11px; + letter-spacing: .11em; + font-weight: 600; + line-height: 13px; + text-transform: uppercase; +} + +.lnurl-tip .close { + position: absolute; + top: 12px; + right: 16px; + color: var(--font-secondary-color); + cursor: pointer; +} + +.lnurl-tip .close:hover { + color: var(--font-tertiary-color); +} + +.lnurl-tip .header { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 32px; +} + +.lnurl-tip .header h2 { + margin: 0; + flex-grow: 1; + font-weight: 600; + font-size: 16px; + line-height: 19px; } .lnurl-tip .btn { @@ -9,17 +62,39 @@ } .lnurl-tip .btn:hover { - background-color: var(--gray); +} + +.amounts { + display: flex; + width: 100%; + overflow-x: auto; + scrollbar-width: none; /* Firefox */ + margin-bottom: 16px; +} + +.amounts::--webkit-scrollbar { + display: none; } .sat-amount { + text-align: center; display: inline-block; - background-color: var(--gray-secondary); + background-color: #2A2A2A; color: var(--font-color); - padding: 2px 10px; - border-radius: 10px; + padding: 12px 16px; + border-radius: 100px; user-select: none; - margin: 2px 5px; + font-weight: 600; + font-size: 14px; + line-height: 17px; +} + +.light .sat-amount { + background-color: var(--gray); +} + +.sat-amount:not(:last-child) { + margin-right: 8px; } .sat-amount:hover { @@ -50,10 +125,45 @@ margin: 10px auto; } -.lnurl-tip .invoice .actions .pay-actions { - margin: 10px auto; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; +.lnurl-tip .invoice .actions .wallet-action { + width: 100%; + height: 40px; +} + +.lnurl-tip .zap-action { + margin-top: 16px; + width: 100%; + height: 40px; +} + +.lnurl-tip .zap-action svg { + margin-right: 10px; +} + +.lnurl-tip .zap-action-container { + display: flex; + align-items: center; + justify-content: center; +} + +.lnurl-tip .custom-amount { + margin-bottom: 16px; +} + +.lnurl-tip .custom-amount button { + padding: 12px 18px; + border-radius: 100px; +} + +.lnurl-tip canvas { + border-radius: 10px; +} + +.lnurl-tip .success-action .paid { + font-size: 19px; +} + +.lnurl-tip .success-action a { + color: var(--highlight); + font-size: 19px; } diff --git a/src/Element/LNURLTip.tsx b/src/Element/LNURLTip.tsx index e208e5b8..675fef9c 100644 --- a/src/Element/LNURLTip.tsx +++ b/src/Element/LNURLTip.tsx @@ -1,8 +1,14 @@ import "./LNURLTip.css"; import { useEffect, useMemo, useState } from "react"; + +import { formatShort } from "Number"; import { bech32ToText } from "Util"; import { HexKey } from "Nostr"; +import Check from "Icons/Check"; +import Zap from "Icons/Zap"; +import Close from "Icons/Close"; import useEventPublisher from "Feed/EventPublisher"; +import ProfileImage from "Element/ProfileImage"; import Modal from "Element/Modal"; import QrCode from "Element/QrCode"; import Copy from "Element/Copy"; @@ -34,6 +40,7 @@ export interface LNURLTipProps { invoice?: string, // shortcut to invoice qr tab title?: string, notice?: string + target?: string note?: HexKey author?: HexKey } @@ -42,10 +49,16 @@ export default function LNURLTip(props: LNURLTipProps) { const onClose = props.onClose || (() => { }); const service = props.svc; const show = props.show || false; - const { note, author } = props - const amounts = [50, 100, 500, 1_000, 5_000, 10_000, 50_000]; + const { note, author, target } = props + const amounts = [500, 1_000, 5_000, 10_000, 20_000]; + const emojis: Record = { + 1_000: "👍", + 5_000: "💜", + 10_000: "😍", + 20_000: "🤩" + } const [payService, setPayService] = useState(); - const [amount, setAmount] = useState(); + const [amount, setAmount] = useState(500); const [customAmount, setCustomAmount] = useState(); const [invoice, setInvoice] = useState(); const [comment, setComment] = useState(); @@ -63,7 +76,7 @@ export default function LNURLTip(props: LNURLTipProps) { setPayService(undefined); setError(undefined); setInvoice(props.invoice ? { pr: props.invoice } : undefined); - setAmount(undefined); + setAmount(500); setComment(undefined); setSuccess(undefined); } @@ -158,9 +171,24 @@ export default function LNURLTip(props: LNURLTipProps) { let min = (payService?.minSendable ?? 0) / 1000; let max = (payService?.maxSendable ?? 21_000_000_000) / 1000; return ( -
- setCustomAmount(parseInt(e.target.value))} /> -
selectAmount(customAmount!)}>Confirm
+
+ setCustomAmount(parseInt(e.target.value))} + /> +
); } @@ -182,22 +210,36 @@ export default function LNURLTip(props: LNURLTipProps) { if (invoice) return null; return ( <> -
{metadata?.description ?? service}
+

Zap amount in sats

+
+ {serviceAmounts.map(a => + selectAmount(a)}> + {emojis[a] && <>{emojis[a]}  } + {formatShort(a)} + + )} +
+ {payService && custom()}
- {(payService?.commentAllowed ?? 0) > 0 ? - setComment(e.target.value)} /> : null} + {(payService?.commentAllowed ?? 0) > 0 && + setComment(e.target.value)} + /> + }
-
- {serviceAmounts.map(a => selectAmount(a)}> - {a.toLocaleString()} - )} - {payService ? - selectAmount(-1)}> - Custom - : null} -
- {amount === -1 ? custom() : null} - {(amount ?? 0) > 0 && } + {(amount ?? 0) > 0 && ( + + )} ) } @@ -208,22 +250,20 @@ export default function LNURLTip(props: LNURLTipProps) { return ( <>
- {props.notice && {props.notice}} - -
- {pr && ( - <> -
- -
-
- -
- - )} -
+ {props.notice && {props.notice}} + +
+ {pr && ( + <> +
+ +
+ + + )} +
) @@ -232,24 +272,46 @@ export default function LNURLTip(props: LNURLTipProps) { function successAction() { if (!success) return null; return ( - <> -

{success?.description ?? "Paid!"}

- {success.url ? {success.url} : null} - +
+

+ + {success?.description ?? "Paid!"} +

+ {success.url && +

+ + yo{success.url} + +

+ } +
) } - const defaultTitle = payService?.nostrPubkey ? "⚡️ Send Zap!" : "⚡️ Send sats"; + const defaultTitle = payService?.nostrPubkey ? "Send zap" : "Send sats"; + const title = target ? `${defaultTitle} to ${target}` : defaultTitle if (!show) return null; return ( - -
e.stopPropagation()}> -

{props.title || defaultTitle}

- {invoiceForm()} - {error ?

{error}

: null} - {payInvoice()} - {successAction()} -
+ +
e.stopPropagation()}> +
+ +
+
+ {author && } +

+ {props.title || title} +

+
+ {invoiceForm()} + {error &&

{error}

} + {payInvoice()} + {successAction()} +
) } diff --git a/src/Element/NoteCreator.css b/src/Element/NoteCreator.css index ad0a7d62..98ac2ce4 100644 --- a/src/Element/NoteCreator.css +++ b/src/Element/NoteCreator.css @@ -12,6 +12,7 @@ } .note-creator textarea { + border: none; outline: none; resize: none; background-color: var(--note-bg); diff --git a/src/Element/NoteFooter.tsx b/src/Element/NoteFooter.tsx index e11be6ce..2da126e1 100644 --- a/src/Element/NoteFooter.tsx +++ b/src/Element/NoteFooter.tsx @@ -268,7 +268,14 @@ export default function NoteFooter(props: NoteFooterProps) { show={reply} setShow={setReply} /> - setTip(false)} show={tip} author={author?.pubkey} note={ev.Id} /> + setTip(false)} + show={tip} + author={author?.pubkey} + target={author?.display_name || author?.name} + note={ev.Id} + />
diff --git a/src/Element/Tabs.css b/src/Element/Tabs.css index 2b854d91..769c1a72 100644 --- a/src/Element/Tabs.css +++ b/src/Element/Tabs.css @@ -12,7 +12,8 @@ } .tab { - border: 1px solid var(--gray-secondary); + color: var(--font-tertiary-color); + border: 1px solid var(--font-tertiary-color); border-radius: 16px; text-align: center; font-weight: 600; @@ -21,7 +22,6 @@ font-weight: 600; font-size: 14px; line-height: 17px; - color: #A3A3A3; margin-right: 12px; } diff --git a/src/Element/Zap.css b/src/Element/Zap.css index 5de0871b..cb66101e 100644 --- a/src/Element/Zap.css +++ b/src/Element/Zap.css @@ -52,7 +52,7 @@ margin-top: 8px; display: flex; flex-direction: row; - margin-left: 52px; + margin-left: 56px; } .note.thread-root .zaps-summary { @@ -70,8 +70,8 @@ } .top-zap .avatar { - width: 21px; - height: 21px; + width: 18px; + height: 18px; } .top-zap .nip05 { diff --git a/src/Element/ZapButton.tsx b/src/Element/ZapButton.tsx index 4195e25a..a48fe1ac 100644 --- a/src/Element/ZapButton.tsx +++ b/src/Element/ZapButton.tsx @@ -19,7 +19,7 @@ const ZapButton = ({ pubkey, svc }: { pubkey?: HexKey, svc?: string }) => {
setZap(true)}>
- setZap(false)} author={pubkey} /> + setZap(false)} author={pubkey} /> ) } diff --git a/src/Icons/Close.tsx b/src/Icons/Close.tsx new file mode 100644 index 00000000..0c038328 --- /dev/null +++ b/src/Icons/Close.tsx @@ -0,0 +1,11 @@ +import IconProps from "./IconProps"; + +const Close = (props: IconProps) => { + return ( + + + + ) +} + +export default Close diff --git a/src/Icons/Reply.tsx b/src/Icons/Reply.tsx index fa57e467..3d9cf0ba 100644 --- a/src/Icons/Reply.tsx +++ b/src/Icons/Reply.tsx @@ -1,8 +1,10 @@ +import IconProps from "./IconProps"; + const Reply = () => { return ( - - - + + + ) } diff --git a/src/Pages/ProfilePage.tsx b/src/Pages/ProfilePage.tsx index 2310c079..b77fa060 100644 --- a/src/Pages/ProfilePage.tsx +++ b/src/Pages/ProfilePage.tsx @@ -111,7 +111,13 @@ export default function ProfilePage() {
)} - setShowLnQr(false)} author={id} /> + setShowLnQr(false)} + author={id} + target={user?.display_name || user?.name} + /> ) } diff --git a/src/index.css b/src/index.css index 692e33e6..925d7053 100644 --- a/src/index.css +++ b/src/index.css @@ -3,8 +3,8 @@ :root { --bg-color: #000; --font-color: #FFF; - --font-secondary-color: #7B7B7B; - --font-tertiary-color: #666; + --font-secondary-color: #A7A7A7; + --font-tertiary-color: #A3A3A3; --font-size: 16px; --font-size-small: 14px; --font-size-tiny: 12px; @@ -34,7 +34,7 @@ html.light { --bg-color: #F1F1F1; --font-color: #57534E; --font-secondary-color: #7B7B7B; - --font-tertiary-color: #F3F3F3; + --font-tertiary-color: #A7A7A7; --highlight-light: #16AAC1; --highlight: #0284C7; @@ -126,18 +126,19 @@ button { } button:disabled { + opacity: 0.3; + cursor: not-allowed; +} + +button.secondary:disabled { + color: var(--font-secondary-color); cursor: not-allowed; - color: var(--font-color); - background-color: transparent; - border: 1px solid var(--font-secondary-color); } button:disabled:hover { cursor: not-allowed; color: var(--font-color); - background-color: transparent; - background-color: var(--gray-superdark); - border: 1px solid var(--font-secondary-color); + border-color: var(--gray-superdark); } .light button.transparent { @@ -239,14 +240,12 @@ button.icon:hover { } .btn-rnd { - border-radius: 100%; - border-color: var(--gray-secondary); + border: none; width: 21px; height: 21px; display: flex; align-items: center; justify-content: center; - margin-right: 16px; } @media (min-width: 520px) { @@ -257,12 +256,21 @@ textarea { font: inherit; } -input[type="text"], input[type="password"], input[type="number"], textarea, select { - padding: 10px; - border-radius: 5px; - border: 0; - background-color: var(--gray); +input[type="text"], input[type="password"], input[type="number"], select, textarea { + padding: 12px; color: var(--font-color); + background: transparent; + border: 1px solid rgba(255, 255, 255, 0.1); + border-radius: 16px; + outline: none; +} + +.light input[type="text"], .light input[type="password"], .light input[type="number"], .light select, .light textarea { + border: 1px solid rgba(0, 0, 0, 0.3); +} + +input:placeholder, textarea:placeholder { + color: var(--font-tertiary-color); } input[type="checkbox"] { @@ -275,10 +283,6 @@ input:disabled { cursor: not-allowed; } -textarea:placeholder { - color: var(--gray-superlight); -} - .flex { display: flex; align-items: center; @@ -451,6 +455,10 @@ body.scroll-lock { background-color: var(--error); } +.success { + color: var(--success); +} + .bg-success { background-color: var(--success); }