feat: show check mark when zapped

This commit is contained in:
Shusui MOYATANI
2024-01-14 23:17:42 +09:00
parent 3d4eba023d
commit 620870a801
3 changed files with 67 additions and 20 deletions

View File

@@ -12,6 +12,8 @@ import {
import { createMutation } from '@tanstack/solid-query';
import Bolt from 'heroicons/24/outline/bolt.svg';
import Check from 'heroicons/24/solid/check.svg';
import * as Kind from 'nostr-tools/kinds';
import { type Event as NostrEvent } from 'nostr-tools/pure';
import qrcode from 'qrcode';
import { requestProvider, type WebLNProvider } from 'webln';
@@ -23,15 +25,18 @@ import useConfig from '@/core/useConfig';
import { useTranslation } from '@/i18n/useTranslation';
import createZapRequest from '@/nostr/builder/createZapRequest';
import { genericEvent } from '@/nostr/event';
import ZapReceipt from '@/nostr/event/ZapReceipt';
import { signEvent } from '@/nostr/useCommands';
import useLnurlEndpoint from '@/nostr/useLnurlEndpoint';
import useProfile from '@/nostr/useProfile';
import usePubkey from '@/nostr/usePubkey';
import useSubscription from '@/nostr/useSubscription';
import fetchLnurlCallback, { type FetchLnurlCallbackParams } from '@/nostr/zap/fetchLnurlCallback';
import lud06ToLnurlPayUrl from '@/nostr/zap/lud06ToLnurlPayUrl';
import lud16ToLnurlPayUrl from '@/nostr/zap/lud16ToLnurlPayUrl';
import verifyInvoice from '@/nostr/zap/verifyInvoice';
import ensureNonNull from '@/utils/ensureNonNull';
import epoch from '@/utils/epoch';
export type ZapRequestModalProps = {
event: NostrEvent;
@@ -90,12 +95,34 @@ const QRCodeDisplay: Component<{ text: string }> = (props) => {
return <canvas width="256" height="256" ref={canvasRef} />;
};
const InvoiceDisplay: Component<{ invoice: string }> = (props) => {
const InvoiceDisplay: Component<{ invoice: string; event: NostrEvent; nostrPubkey?: string }> = (
props,
) => {
const i18n = useTranslation();
const { config } = useConfig();
const webln = useWebLN();
const lightingInvoice = () => `lightning:${props.invoice}`;
const { events } = useSubscription(() =>
ensureNonNull([props.nostrPubkey] as const)(([nostrPubkey]) => ({
relayUrls: config().relayUrls,
filters: [
{
kinds: [Kind.Zap],
authors: nostrPubkey != null ? [nostrPubkey] : undefined,
'#p': [props.event.pubkey],
'#e': [props.event.id],
since: epoch(),
},
],
continuous: true,
})),
);
const zapped = () =>
events().find((ev) => new ZapReceipt(ev).bolt11().paymentRequest === props.invoice);
const handleClickWebLN = () => {
const provider = webln.provider();
if (provider == null) return;
@@ -112,6 +139,17 @@ const InvoiceDisplay: Component<{ invoice: string }> = (props) => {
};
return (
<Show
when={zapped()}
fallback={
<div class="flex flex-col items-center gap-4 py-8">
<span class="inline-block h-28 w-28 rounded-full border-4 border-primary p-4 text-primary">
<Check />
</span>
<div class="text-secondary text-xl">{i18n()('zap.completed')}</div>
</div>
}
>
<div class="flex flex-col items-center gap-2">
<div>
<QRCodeDisplay text={lightingInvoice()} />
@@ -132,6 +170,7 @@ const InvoiceDisplay: Component<{ invoice: string }> = (props) => {
</button>
</Show>
</div>
</Show>
);
};
@@ -250,7 +289,13 @@ const ZapDialog: Component<ZapDialogProps> = (props) => {
{i18n()('zap.fetchingLnUrlInvoiceError')}: {getInvoiceMutation?.error?.message}
</Match>
<Match when={getInvoiceMutation.isSuccess && getInvoiceMutation.data} keyed>
{(invoice) => <InvoiceDisplay invoice={invoice} />}
{(invoice) => (
<InvoiceDisplay
invoice={invoice}
event={props.event}
nostrPubkey={endpoint()?.nostrPubkey}
/>
)}
</Match>
<Match when={query.isSuccess}>
<div class="flex flex-col items-center">

View File

@@ -138,6 +138,7 @@ export default {
comment: 'Comment (optional)',
sendViaWallet: 'Send via wallet',
sendViaWebLN: 'Send via extension',
completed: 'Completed',
},
config: {
config: 'Settings',

View File

@@ -134,6 +134,7 @@ export default {
comment: 'コメント (任意)',
sendViaWallet: 'ウォレットで送る',
sendViaWebLN: '拡張機能で送る',
completed: '完了',
},
config: {
config: '設定',