8 changed files with 183 additions and 84 deletions
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<script lang="ts"> |
||||
import { HeartOutline, FilePenOutline, AnnotationOutline } from 'flowbite-svelte-icons'; |
||||
import ZapOutline from "$components/util/ZapOutline.svelte"; |
||||
import type { NDKEvent } from "@nostr-dev-kit/ndk"; |
||||
import { onMount } from "svelte"; |
||||
import { ndkInstance } from '$lib/ndk'; |
||||
|
||||
const { rootId, event } = $props<{ rootId: String, event: NDKEvent }>(); |
||||
|
||||
// Reactive arrays to hold incoming events |
||||
let likes: NDKEvent[] = []; |
||||
let zaps: NDKEvent[] = []; |
||||
let highlights: NDKEvent[] = []; |
||||
let comments: NDKEvent[] = []; |
||||
|
||||
// Reactive counts derived from array lengths |
||||
// Derived counts from store values |
||||
const likeCount = $derived(likes.length); |
||||
const zapCount = $derived(zaps.length); |
||||
const highlightCount = $derived(highlights.length); |
||||
const commentCount = $derived(comments.length); |
||||
|
||||
/** |
||||
* Subscribe to Nostr events of a given kind that reference our root event via e-tag. |
||||
* Push new events into the provided array if not already present. |
||||
* Returns the subscription for later cleanup. |
||||
*/ |
||||
function subscribeCount(kind: number, targetArray: NDKEvent[]) { |
||||
const sub = $ndkInstance.subscribe({ |
||||
kinds: [kind], |
||||
'#a': [rootId] |
||||
}); |
||||
|
||||
|
||||
sub.on('event', (evt: NDKEvent) => { |
||||
// Only add if we haven't seen this event ID yet |
||||
if (!targetArray.find(e => e.id === evt.id)) { |
||||
targetArray.push(evt); |
||||
} |
||||
}); |
||||
|
||||
return sub; |
||||
} |
||||
|
||||
let subs: any[] = []; |
||||
|
||||
onMount(() => { |
||||
// Subscribe to each kind; store subs for cleanup |
||||
subs.push(subscribeCount(7, likes)); // likes (Reaction) |
||||
subs.push(subscribeCount(9735, zaps)); // zaps (Zap Receipts) |
||||
subs.push(subscribeCount(30023, highlights)); // highlights (custom kind) |
||||
subs.push(subscribeCount(1, comments)); // comments (Text Notes) |
||||
}); |
||||
|
||||
</script> |
||||
|
||||
<div class='InteractiveMenu flex flex-row justify-around align-middle text-primary-600 dark:text-gray-500'> |
||||
<div class='flex flex-row shrink-0 min-w-11'><HeartOutline size="lg" /><span>{likeCount}</span></div> |
||||
<div class='flex flex-row shrink-0 min-w-11'><ZapOutline /><span>{zapCount}</span></div> |
||||
<div class='flex flex-row shrink-0 min-w-11'><FilePenOutline size="lg"/><span>{highlightCount}</span></div> |
||||
<div class='flex flex-row shrink-0 min-w-11'><AnnotationOutline size="lg"/><span>{commentCount}</span></div> |
||||
</div> |
||||
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<script> |
||||
export let size = 24; // default size |
||||
export let className = ''; |
||||
</script> |
||||
|
||||
<svg |
||||
xmlns="http://www.w3.org/2000/svg" |
||||
width={size} |
||||
height={size} |
||||
fill="none" |
||||
stroke="currentColor" |
||||
stroke-width="2" |
||||
stroke-linecap="round" |
||||
stroke-linejoin="round" |
||||
class={className} |
||||
viewBox="0 0 24 24" |
||||
> |
||||
<polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/> |
||||
</svg> |
||||
Loading…
Reference in new issue