mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 00:10:52 +00:00
Add cross-posting
This commit is contained in:
parent
5e3c919245
commit
54d738aefa
1
.env
1
.env
@ -4,6 +4,7 @@ VITE_DEFAULT_RELAYS=wss://purplepag.es,wss://relay.damus.io,wss://relay.nostr.ba
|
||||
VITE_DEFAULT_FOLLOWS=1739d937dc8c0c7370aa27585938c119e25c41f6c441a5d34c6d38503e3136ef,fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52,cc8d072efdcc676fcbac14f6cd6825edc3576e55eb786a2a975ee034a6a026cb,d91191e30e00444b942c0e82cad470b32af171764c2275bee0bd99377efd4075,3335d373e6c1b5bc669b4b1220c08728ea8ce622e5a7cfeeb4c0001d91ded1de,0b118e40d6f3dfabb17f21a94a647701f140d8b063a9e84fe6e483644edc09cb,b83a28b7e4e5d20bd960c5faeb6625f95529166b8bdb045d42634a2f35919450,958b754a1d3de5b5eca0fe31d2d555f451325f8498a83da1997b7fcd5c39e88c,b9e76546ba06456ed301d9e52bc49fa48e70a6bf2282be7a1ae72947612023dc,b708f7392f588406212c3882e7b3bc0d9b08d62f95fa170d099127ece2770e5e,5c508c34f58866ec7341aaf10cc1af52e9232bb9f859c8103ca5ecf2aa93bf78,baf27a4cc4da49913e7fdecc951fd3b971c9279959af62b02b761a043c33384c,2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884,0fecf65daa26faf3f668e8143325a4c199a040b6345ed40a08614d7dd85b1823,1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411,f783ba3b12b91e375aba6594015b90bd95f7e132b03cc8c4c52ce0a7c36aab52,3f770d65d3a764a9c5cb503ae123e62ec7598ad035d836e2a810f3877a745b24,82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2,3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d,ee11a5dff40c19a555f41fe42b48f00e618c91225622ae37b6c2bb67b76c4e49,97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322,a1fc5dfd7ffcf563c89155b466751b580d115e136e2f8c90e8913385bbedb1cf,84dee6e676e5bb67b4ad4e042cf70cbd8681155db535942fcc6a0533858a7240
|
||||
VITE_IMGPROXY_URL=https://imgproxy.coracle.social
|
||||
VITE_DUFFLEPUD_URL=https://dufflepud.onrender.com
|
||||
VITE_ENABLE_GROUPS=true
|
||||
VITE_ENABLE_ZAPS=true
|
||||
VITE_FORCE_RELAYS=
|
||||
VITE_LOGO_URL=
|
||||
|
@ -154,6 +154,9 @@
|
||||
zapper
|
||||
)
|
||||
|
||||
// Split out reposts
|
||||
$: reposts = children.filter(e => [6, 16].includes(e.kind))
|
||||
|
||||
onMount(async () => {
|
||||
const zapAddress = Tags.from(note).getValue("zap")
|
||||
|
||||
@ -191,6 +194,11 @@
|
||||
kinds.push(9735)
|
||||
}
|
||||
|
||||
if ($env.ENABLE_GROUPS && !event.wrap) {
|
||||
kinds.push(6)
|
||||
kinds.push(16)
|
||||
}
|
||||
|
||||
load({
|
||||
relays: mergeHints([relays, getReplyHints(event)]),
|
||||
filters: getReplyFilters([event], {kinds}),
|
||||
|
@ -3,12 +3,20 @@
|
||||
import {nip19} from "nostr-tools"
|
||||
import {toNostrURI, createEvent} from "paravel"
|
||||
import {tweened} from "svelte/motion"
|
||||
import {identity, sum, pluck, sortBy} from "ramda"
|
||||
import {identity, sum, uniqBy, prop, pluck, sortBy} from "ramda"
|
||||
import {formatSats} from "src/util/misc"
|
||||
import {LOCAL_RELAY_URL, getGroupAddress, asNostrEvent, getIdOrAddress} from "src/util/nostr"
|
||||
import {
|
||||
LOCAL_RELAY_URL,
|
||||
getGroupAddress,
|
||||
getIdOrAddressTag,
|
||||
asNostrEvent,
|
||||
getIdOrAddress,
|
||||
} from "src/util/nostr"
|
||||
import {quantify} from "hurdak"
|
||||
import {toast} from "src/partials/state"
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import ColorDot from "src/partials/ColorDot.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
@ -16,15 +24,18 @@
|
||||
import CopyValue from "src/partials/CopyValue.svelte"
|
||||
import PersonBadge from "src/app/shared/PersonBadge.svelte"
|
||||
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||
import GroupSummary from "src/app/shared/GroupSummary.svelte"
|
||||
import {router} from "src/app/router"
|
||||
import type {Event} from "src/engine"
|
||||
import {
|
||||
env,
|
||||
mute,
|
||||
unmute,
|
||||
groups,
|
||||
canSign,
|
||||
session,
|
||||
Publisher,
|
||||
mention,
|
||||
signer,
|
||||
deriveGroupAccess,
|
||||
publishToZeroOrMoreGroups,
|
||||
@ -44,11 +55,10 @@
|
||||
export let showMuted
|
||||
export let showEntire
|
||||
export let removeFromContext
|
||||
export let replies
|
||||
export let likes
|
||||
export let zaps
|
||||
export let replies, likes, zaps
|
||||
export let zapper
|
||||
|
||||
const address = getGroupAddress(note)
|
||||
const relays = getEventHints(note)
|
||||
const nevent = nip19.neventEncode({id: note.id, relays})
|
||||
const muted = isEventMuted.derived($isEventMuted => $isEventMuted(note, true))
|
||||
@ -59,6 +69,10 @@
|
||||
|
||||
//const report = () => router.at("notes").of(note.id, {relays: getEventHints(note)}).at('report').qp({pubkey: note.pubkey}).open()
|
||||
|
||||
const setView = v => {
|
||||
view = v
|
||||
}
|
||||
|
||||
const label = () => router.at("notes").of(note.id, {relays}).at("label").open()
|
||||
|
||||
const quote = () => router.at("notes/create").cx({quote: note, relays}).open()
|
||||
@ -87,6 +101,24 @@
|
||||
removeFromContext(e)
|
||||
}
|
||||
|
||||
const crossPost = async address => {
|
||||
const relays = getPublishHints(note)
|
||||
const tags = [getIdOrAddressTag(note, relays[0]), mention(note.pubkey)]
|
||||
const content = JSON.stringify(asNostrEvent(note))
|
||||
const shouldWrap = groups.key(address).get()?.access === "closed"
|
||||
|
||||
let template
|
||||
if (note.kind === 1) {
|
||||
template = createEvent(6, {content, tags})
|
||||
} else {
|
||||
template = createEvent(16, {content, tags: [...tags, ["k", note.kind]]})
|
||||
}
|
||||
|
||||
publishToZeroOrMoreGroups([address], template, {relays, shouldWrap})
|
||||
|
||||
setView(null)
|
||||
}
|
||||
|
||||
const startZap = () =>
|
||||
router
|
||||
.at("people")
|
||||
@ -110,11 +142,24 @@
|
||||
.cx({relays: [url]})
|
||||
.open()
|
||||
|
||||
let like, allLikes, zap
|
||||
let showDetails = false
|
||||
const groupOptions = session.derived($session => {
|
||||
const options = []
|
||||
|
||||
for (const addr of Object.keys($session.groups || {})) {
|
||||
const group = groups.key(addr).get()
|
||||
const access = deriveGroupAccess(addr).get()
|
||||
|
||||
if (group && access === "granted" && addr !== address) {
|
||||
options.push(group)
|
||||
}
|
||||
}
|
||||
|
||||
return uniqBy(prop("address"), options)
|
||||
})
|
||||
|
||||
let view
|
||||
let actions = []
|
||||
|
||||
$: address = getGroupAddress(note)
|
||||
$: disableActions =
|
||||
!$canSign ||
|
||||
($muted && !showMuted) ||
|
||||
@ -140,6 +185,7 @@
|
||||
actions = []
|
||||
|
||||
actions.push({label: "Quote", icon: "quote-left", onClick: quote})
|
||||
actions.push({label: "Cross-post", icon: "shuffle", onClick: () => setView('cross-post')})
|
||||
actions.push({label: "Tag", icon: "tag", onClick: label})
|
||||
//actions.push({label: "Report", icon: "triangle-exclamation", onClick: report})
|
||||
|
||||
@ -156,9 +202,7 @@
|
||||
actions.push({
|
||||
label: "Details",
|
||||
icon: "info",
|
||||
onClick: () => {
|
||||
showDetails = true
|
||||
},
|
||||
onClick: () => setView("info"),
|
||||
})
|
||||
}
|
||||
</script>
|
||||
@ -243,43 +287,67 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if showDetails}
|
||||
<Modal
|
||||
onEscape={() => {
|
||||
showDetails = false
|
||||
}}>
|
||||
{#if view}
|
||||
<Modal onEscape={() => setView(null)}>
|
||||
<Content>
|
||||
{#if zaps.length > 0}
|
||||
<h1 class="staatliches text-2xl">Zapped By</h1>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each zaps as zap}
|
||||
<div class="flex flex-col gap-1">
|
||||
<PersonBadge pubkey={zap.request.pubkey} />
|
||||
<span class="ml-16 text-sm text-gray-5"
|
||||
>{formatSats(zap.invoiceAmount / 1000)} sats</span>
|
||||
{#if view === "info"}
|
||||
{#if zaps.length > 0}
|
||||
<h1 class="staatliches text-2xl">Zapped By</h1>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each zaps as zap}
|
||||
<div class="flex flex-col gap-1">
|
||||
<PersonBadge pubkey={zap.request.pubkey} />
|
||||
<span class="ml-16 text-sm text-gray-5"
|
||||
>{formatSats(zap.invoiceAmount / 1000)} sats</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if likes.length > 0}
|
||||
<h1 class="staatliches text-2xl">Liked By</h1>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each likes as like}
|
||||
<PersonBadge pubkey={like.pubkey} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if note.seen_on.length > 0}
|
||||
<h1 class="staatliches text-2xl">Relays</h1>
|
||||
<p>This note was found on {quantify(note.seen_on.length, "relay")} below.</p>
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each note.seen_on as url}
|
||||
<RelayCard relay={{url}} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<h1 class="staatliches text-2xl">Details</h1>
|
||||
<CopyValue label="Link" value={toNostrURI(nevent)} />
|
||||
<CopyValue label="Event ID" encode={nip19.noteEncode} value={note.id} />
|
||||
<CopyValue label="Event JSON" value={JSON.stringify(asNostrEvent(note))} />
|
||||
{:else if view === "cross-post"}
|
||||
<div class="mb-4 flex items-center justify-center">
|
||||
<Heading>Cross-post</Heading>
|
||||
</div>
|
||||
<div>Select where you'd like to post to:</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
{#if address}
|
||||
<Card invertColors interactive on:click={() => crossPost()}>
|
||||
<div class="flex gap-4 text-gray-1">
|
||||
<i class="fa fa-earth-asia fa-2x" />
|
||||
<div class="flex min-w-0 flex-grow flex-col gap-4">
|
||||
<p class="text-2xl">Global</p>
|
||||
<p>Post to your main feed.</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
{/if}
|
||||
{#each $groupOptions as g (g.address)}
|
||||
<Card invertColors interactive on:click={() => crossPost(g.address)}>
|
||||
<GroupSummary address={g.address} />
|
||||
</Card>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{#if likes.length > 0}
|
||||
<h1 class="staatliches text-2xl">Liked By</h1>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
{#each likes as like}
|
||||
<PersonBadge pubkey={like.pubkey} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<h1 class="staatliches text-2xl">Relays</h1>
|
||||
<p>This note was found on {quantify(note.seen_on.length, "relay")} below.</p>
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each note.seen_on as url}
|
||||
<RelayCard relay={{url}} />
|
||||
{/each}
|
||||
</div>
|
||||
<h1 class="staatliches text-2xl">Details</h1>
|
||||
<CopyValue label="Link" value={toNostrURI(nevent)} />
|
||||
<CopyValue label="Event ID" encode={nip19.noteEncode} value={note.id} />
|
||||
<CopyValue label="Event JSON" value={JSON.stringify(asNostrEvent(note))} />
|
||||
</Content>
|
||||
</Modal>
|
||||
{/if}
|
||||
|
@ -46,8 +46,7 @@ const MULTIPLEXTR_URL = import.meta.env.VITE_MULTIPLEXTR_URL
|
||||
|
||||
const FORCE_RELAYS = fromCsv(import.meta.env.VITE_FORCE_RELAYS)
|
||||
|
||||
const DVM_RELAYS =
|
||||
FORCE_RELAYS.length > 0 ? FORCE_RELAYS : fromCsv(import.meta.env.VITE_DVM_RELAYS)
|
||||
const DVM_RELAYS = FORCE_RELAYS.length > 0 ? FORCE_RELAYS : fromCsv(import.meta.env.VITE_DVM_RELAYS)
|
||||
|
||||
const SEARCH_RELAYS =
|
||||
FORCE_RELAYS.length > 0 ? FORCE_RELAYS : ["wss://relay.nostr.band", "wss://nostr.wine"]
|
||||
@ -59,6 +58,8 @@ const DEFAULT_FOLLOWS = fromCsv(import.meta.env.VITE_DEFAULT_FOLLOWS)
|
||||
|
||||
const ENABLE_ZAPS = JSON.parse(import.meta.env.VITE_ENABLE_ZAPS)
|
||||
|
||||
const ENABLE_GROUPS = JSON.parse(import.meta.env.VITE_ENABLE_GROUPS)
|
||||
|
||||
// Prep our env
|
||||
env.set({
|
||||
DEFAULT_FOLLOWS,
|
||||
@ -70,6 +71,7 @@ env.set({
|
||||
SEARCH_RELAYS,
|
||||
DEFAULT_RELAYS,
|
||||
ENABLE_ZAPS,
|
||||
ENABLE_GROUPS,
|
||||
})
|
||||
|
||||
// Throw some hardcoded defaults in there
|
||||
|
@ -62,6 +62,13 @@ export const getIdOrAddress = e => {
|
||||
return e.id
|
||||
}
|
||||
|
||||
export const getIdOrAddressTag = (e, hint) => {
|
||||
const value = getIdOrAddress(e)
|
||||
const type = value.includes(":") ? "a" : "e"
|
||||
|
||||
return [type, value, hint]
|
||||
}
|
||||
|
||||
export const getGroupAddress = e =>
|
||||
Tags.from(e)
|
||||
.type("a")
|
||||
|
Loading…
Reference in New Issue
Block a user