mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Factor out NoteZap from NoteActions
This commit is contained in:
parent
66b16c4db4
commit
fa1211a2fd
@ -11,6 +11,7 @@
|
||||
import LoginPubKey from "src/app/views/LoginPubKey.svelte"
|
||||
import Onboarding from "src/app/views/Onboarding.svelte"
|
||||
import NoteCreate from "src/app/views/NoteCreate.svelte"
|
||||
import NoteZap from "src/app/views/NoteZap.svelte"
|
||||
import NoteDetail from "src/app/views/NoteDetail.svelte"
|
||||
import PersonFeed from "src/app/views/PersonFeed.svelte"
|
||||
import PersonList from "src/app/shared/PersonList.svelte"
|
||||
@ -39,6 +40,8 @@
|
||||
{/key}
|
||||
{:else if m.type === "note/create"}
|
||||
<NoteCreate pubkey={m.pubkey} nevent={m.nevent} />
|
||||
{:else if m.type === "note/zap"}
|
||||
<NoteZap note={m.note} />
|
||||
{:else if m.type === "relay/add"}
|
||||
<RelayAdd url={m.url} />
|
||||
{:else if m.type === "onboarding"}
|
||||
|
@ -111,7 +111,6 @@
|
||||
|
||||
return () => {
|
||||
clearInterval(interval)
|
||||
actions.cleanupZap()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
@ -3,29 +3,22 @@
|
||||
import {nip19} from "nostr-tools"
|
||||
import {tweened} from "svelte/motion"
|
||||
import {find, reject, identity, propEq, pathEq, sum, pluck, sortBy} from "ramda"
|
||||
import {warn} from "src/util/logger"
|
||||
import {copyToClipboard} from "src/util/html"
|
||||
import {stringToHue, fetchJson, now, formatSats, hsl} from "src/util/misc"
|
||||
import {displayRelay, isLike, displayPerson, processZaps} from "src/util/nostr"
|
||||
import {stringToHue, formatSats, hsl} from "src/util/misc"
|
||||
import {displayRelay, isLike, processZaps} from "src/util/nostr"
|
||||
import {quantify, first} from "hurdak/lib/hurdak"
|
||||
import {toast, modal} from "src/partials/state"
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
import QRCode from "src/partials/QRCode.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import OverflowMenu from "src/partials/OverflowMenu.svelte"
|
||||
import CopyValue from "src/partials/CopyValue.svelte"
|
||||
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Textarea from "src/partials/Textarea.svelte"
|
||||
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||
import {getEventPublishRelays} from "src/agent/relays"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import network from "src/agent/network"
|
||||
import pool from "src/agent/pool"
|
||||
import user from "src/agent/user"
|
||||
import keys from "src/agent/keys"
|
||||
import cmd from "src/agent/cmd"
|
||||
|
||||
export let note
|
||||
@ -66,78 +59,11 @@
|
||||
}
|
||||
|
||||
const startZap = () => {
|
||||
draftZap = {
|
||||
amount: user.getSetting("defaultZap"),
|
||||
message: "",
|
||||
invoice: null,
|
||||
loading: false,
|
||||
startedAt: now(),
|
||||
confirmed: false,
|
||||
}
|
||||
}
|
||||
|
||||
const loadZapInvoice = async () => {
|
||||
draftZap.loading = true
|
||||
|
||||
const {zapper, lnurl} = $author
|
||||
const amount = draftZap.amount * 1000
|
||||
const relays = getEventPublishRelays(note)
|
||||
const urls = pluck("url", relays)
|
||||
const publishable = cmd.requestZap(urls, draftZap.message, note.pubkey, note.id, amount, lnurl)
|
||||
const event = encodeURI(JSON.stringify(await keys.sign(publishable.event)))
|
||||
const res = await fetchJson(`${zapper.callback}?amount=${amount}&nostr=${event}&lnurl=${lnurl}`)
|
||||
|
||||
// If they closed the dialog before fetch resolved, we're done
|
||||
if (!draftZap) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!res.pr) {
|
||||
throw new Error(JSON.stringify(res))
|
||||
}
|
||||
|
||||
draftZap.invoice = res.pr
|
||||
draftZap.loading = false
|
||||
|
||||
// Open up alby or whatever
|
||||
const {webln} = window as {webln?: any}
|
||||
if (webln) {
|
||||
await webln.enable()
|
||||
|
||||
try {
|
||||
webln.sendPayment(draftZap.invoice)
|
||||
} catch (e) {
|
||||
warn(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for the zap confirmation
|
||||
draftZap.sub = network.listen({
|
||||
relays,
|
||||
filter: {
|
||||
kinds: [9735],
|
||||
authors: [zapper.nostrPubkey],
|
||||
"#p": [$author.pubkey],
|
||||
since: draftZap.startedAt - 10,
|
||||
},
|
||||
onChunk: chunk => {
|
||||
zap = first(chunk)
|
||||
draftZap.confirmed = true
|
||||
setTimeout(cleanupZap, 1000)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const cleanupZap = () => {
|
||||
if (draftZap) {
|
||||
draftZap.sub?.then(s => s.unsub())
|
||||
draftZap = null
|
||||
}
|
||||
modal.push({type: "note/zap", note})
|
||||
}
|
||||
|
||||
let like, likes, allLikes, zap, zaps, allZaps
|
||||
let actions = []
|
||||
let draftZap = null
|
||||
let showDetails = false
|
||||
|
||||
$: disableActions = !$canPublish || muted
|
||||
@ -250,44 +176,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if draftZap}
|
||||
<Modal onEscape={cleanupZap}>
|
||||
<Content size="lg">
|
||||
<div class="text-center">
|
||||
<h1 class="staatliches text-2xl">Send a zap</h1>
|
||||
<p>to {displayPerson($author)}</p>
|
||||
</div>
|
||||
{#if draftZap.confirmed}
|
||||
<div class="flex items-center justify-center gap-2 text-gray-1">
|
||||
<i class="fa fa-champagne-glasses" />
|
||||
<p>Success! Zap confirmed.</p>
|
||||
</div>
|
||||
{:else if draftZap.invoice}
|
||||
<QRCode code={draftZap.invoice} />
|
||||
<p class="text-center text-gray-1">
|
||||
Copy or scan using a lightning wallet to pay your zap.
|
||||
</p>
|
||||
<div class="flex items-center justify-center gap-2 text-gray-1">
|
||||
<i class="fa fa-circle-notch fa-spin" />
|
||||
Waiting for confirmation...
|
||||
</div>
|
||||
{:else}
|
||||
<Textarea bind:value={draftZap.message} placeholder="Add an optional message" />
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="flex-grow">Custom amount:</label>
|
||||
<Input bind:value={draftZap.amount}>
|
||||
<i slot="before" class="fa fa-bolt" />
|
||||
<span slot="after" class="-mt-1">sats</span>
|
||||
</Input>
|
||||
<Anchor loading={draftZap.loading} type="button-accent" on:click={loadZapInvoice}>
|
||||
Zap!
|
||||
</Anchor>
|
||||
</div>
|
||||
{/if}
|
||||
</Content>
|
||||
</Modal>
|
||||
{/if}
|
||||
|
||||
{#if showDetails}
|
||||
<Modal
|
||||
onEscape={() => {
|
||||
|
118
src/app/views/NoteZap.svelte
Normal file
118
src/app/views/NoteZap.svelte
Normal file
@ -0,0 +1,118 @@
|
||||
<script lang="ts">
|
||||
import {onDestroy} from "svelte"
|
||||
import {pluck} from "ramda"
|
||||
import {warn} from "src/util/logger"
|
||||
import {fetchJson, now} from "src/util/misc"
|
||||
import {displayPerson} from "src/util/nostr"
|
||||
import {modal} from "src/partials/state"
|
||||
import QRCode from "src/partials/QRCode.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Textarea from "src/partials/Textarea.svelte"
|
||||
import {getEventPublishRelays} from "src/agent/relays"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import network from "src/agent/network"
|
||||
import user from "src/agent/user"
|
||||
import keys from "src/agent/keys"
|
||||
import cmd from "src/agent/cmd"
|
||||
|
||||
export let note
|
||||
|
||||
let sub
|
||||
let zap = {
|
||||
amount: user.getSetting("defaultZap"),
|
||||
message: "",
|
||||
invoice: null,
|
||||
loading: false,
|
||||
startedAt: now(),
|
||||
confirmed: false,
|
||||
}
|
||||
|
||||
const author = getPersonWithFallback(note.pubkey)
|
||||
|
||||
const loadZapInvoice = async () => {
|
||||
zap.loading = true
|
||||
|
||||
const {zapper, lnurl} = author
|
||||
const amount = zap.amount * 1000
|
||||
const relays = getEventPublishRelays(note)
|
||||
const urls = pluck("url", relays)
|
||||
const publishable = cmd.requestZap(urls, zap.message, note.pubkey, note.id, amount, lnurl)
|
||||
const event = encodeURI(JSON.stringify(await keys.sign(publishable.event)))
|
||||
const res = await fetchJson(`${zapper.callback}?amount=${amount}&nostr=${event}&lnurl=${lnurl}`)
|
||||
|
||||
// If they closed the dialog before fetch resolved, we're done
|
||||
if (!zap) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!res.pr) {
|
||||
throw new Error(JSON.stringify(res))
|
||||
}
|
||||
|
||||
zap.invoice = res.pr
|
||||
zap.loading = false
|
||||
|
||||
// Open up alby or whatever
|
||||
const {webln} = window as {webln?: any}
|
||||
if (webln) {
|
||||
await webln.enable()
|
||||
|
||||
try {
|
||||
webln.sendPayment(zap.invoice)
|
||||
} catch (e) {
|
||||
warn(e)
|
||||
}
|
||||
}
|
||||
|
||||
// Listen for the zap confirmation
|
||||
sub = network.listen({
|
||||
relays,
|
||||
filter: {
|
||||
kinds: [9735],
|
||||
authors: [zapper.nostrPubkey],
|
||||
"#p": [note.pubkey],
|
||||
since: zap.startedAt - 10,
|
||||
},
|
||||
onChunk: chunk => {
|
||||
zap.confirmed = true
|
||||
setTimeout(() => modal.pop(), 1000)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
onDestroy(() => {
|
||||
sub?.then(s => s.unsub())
|
||||
})
|
||||
</script>
|
||||
|
||||
<Content size="lg">
|
||||
<div class="text-center">
|
||||
<h1 class="staatliches text-2xl">Send a zap</h1>
|
||||
<p>to {displayPerson(author)}</p>
|
||||
</div>
|
||||
{#if zap.confirmed}
|
||||
<div class="flex items-center justify-center gap-2 text-gray-1">
|
||||
<i class="fa fa-champagne-glasses" />
|
||||
<p>Success! Zap confirmed.</p>
|
||||
</div>
|
||||
{:else if zap.invoice}
|
||||
<QRCode code={zap.invoice} />
|
||||
<p class="text-center text-gray-1">Copy or scan using a lightning wallet to pay your zap.</p>
|
||||
<div class="flex items-center justify-center gap-2 text-gray-1">
|
||||
<i class="fa fa-circle-notch fa-spin" />
|
||||
Waiting for confirmation...
|
||||
</div>
|
||||
{:else}
|
||||
<Textarea bind:value={zap.message} placeholder="Add an optional message" />
|
||||
<div class="flex items-center gap-2">
|
||||
<label class="flex-grow">Custom amount:</label>
|
||||
<Input bind:value={zap.amount}>
|
||||
<i slot="before" class="fa fa-bolt" />
|
||||
<span slot="after" class="-mt-1">sats</span>
|
||||
</Input>
|
||||
<Anchor loading={zap.loading} type="button-accent" on:click={loadZapInvoice}>Zap!</Anchor>
|
||||
</div>
|
||||
{/if}
|
||||
</Content>
|
Loading…
Reference in New Issue
Block a user