- {event &&
}
+ {event &&
}
awarded to
{awardees.map(pk => (
@@ -86,7 +86,7 @@ export function LiveChat({
const starts = findTag(ev, "starts");
return starts ? Number(starts) : unixNow() - WEEK;
}, [ev]);
- const { badges, awards } = useBadges(host, started);
+ const { awards } = useBadgeAwards(host);
const hostMutedPubkeys = useMutedPubkeys(host, true);
const userEmojiPacks = useEmoji(login?.pubkey);
@@ -108,7 +108,7 @@ export function LiveChat({
if (ends) {
extra.push({ kind: -2, created_at: Number(ends) } as TaggedNostrEvent);
}
- return removeUndefined([...feed, ...awards, ...extra])
+ return removeUndefined([...feed, ...awards.map(a => a.event), ...extra])
.filter(a => a.created_at >= started)
.sort((a, b) => b.created_at - a.created_at);
}, [feed, awards]);
@@ -202,7 +202,7 @@ export function LiveChat({
return ;
}
case LIVE_STREAM_CHAT: {
- return ;
+ return ;
}
case LIVE_STREAM_RAID: {
return ;
diff --git a/src/element/event-embed.tsx b/src/element/event-embed.tsx
index f0a13bf..11bfa00 100644
--- a/src/element/event-embed.tsx
+++ b/src/element/event-embed.tsx
@@ -4,7 +4,7 @@ import { Icon } from "./icon";
import { Goal } from "./goal";
import { Note } from "./note";
import { EmojiPack } from "./emoji-pack";
-import { Badge } from "./badge";
+import { BadgeInfo } from "./badge";
import { GOAL, LIVE_STREAM_CLIP, StreamState } from "@/const";
import { useEventFeed } from "@snort/system-react";
import LiveStreamClip from "./stream/clip";
@@ -39,7 +39,7 @@ export function NostrEvent({ ev }: { ev: TaggedNostrEvent }) {
return ;
}
case EventKind.Badge: {
- return ;
+ return ;
}
case EventKind.TextNote: {
return ;
diff --git a/src/hooks/badges.ts b/src/hooks/badges.ts
index 7aa833c..5df4591 100644
--- a/src/hooks/badges.ts
+++ b/src/hooks/badges.ts
@@ -1,69 +1,45 @@
import { useMemo } from "react";
-import { EventKind, RequestBuilder, TaggedNostrEvent } from "@snort/system";
+import { EventKind, NostrLink, RequestBuilder, TaggedNostrEvent } from "@snort/system";
import { useRequestBuilder } from "@snort/system-react";
-import { findTag, getTagValues, toAddress } from "@/utils";
-import type { Badge } from "@/types";
+export interface BadgeAward {
+ event: TaggedNostrEvent;
+ awardees: Set;
+}
-export function useBadges(
- pubkey: string,
- since: number,
- leaveOpen = true,
-): { badges: Badge[]; awards: TaggedNostrEvent[] } {
- const rb = useMemo(() => {
+export function useBadgeAwards(pubkey: string, leaveOpen = true) {
+ const subBadgeAwards = useMemo(() => {
const rb = new RequestBuilder(`badges:${pubkey}`);
rb.withOptions({ leaveOpen });
if (pubkey) {
- rb.withFilter().authors([pubkey]).kinds([EventKind.Badge, EventKind.BadgeAward]);
+ rb.withFilter().authors([pubkey]).kinds([EventKind.BadgeAward]);
}
return rb;
- }, [pubkey, since]);
+ }, [pubkey]);
- const badgeEvents = useRequestBuilder(rb);
-
- const rawBadges = useMemo(() => {
- if (badgeEvents) {
- return badgeEvents.filter(e => e.kind === EventKind.Badge).sort((a, b) => b.created_at - a.created_at);
- }
- return [];
- }, [badgeEvents]);
- const badgeAwards = useMemo(() => {
- if (badgeEvents) {
- return badgeEvents.filter(e => e.kind === EventKind.BadgeAward);
- }
- return [];
- }, [badgeEvents]);
-
- const acceptedSub = useMemo(() => {
- const rb = new RequestBuilder(`accepted-badges:${pubkey}`);
- if (rawBadges.length > 0) {
- rb.withFilter().kinds([EventKind.ProfileBadges]).tag("d", ["profile_badges"]).tag("a", rawBadges.map(toAddress));
- }
- return rb;
- }, [rawBadges]);
-
- const acceptedStream = useRequestBuilder(acceptedSub);
- const acceptedEvents = acceptedStream ?? [];
-
- const badges = useMemo(() => {
- return rawBadges.map(e => {
- const name = findTag(e, "d") ?? "";
- const address = toAddress(e);
- const awardEvents = badgeAwards.filter(b => findTag(b, "a") === address);
- const awardees = new Set(awardEvents.map(e => getTagValues(e.tags, "p")).flat());
- const accepted = new Set(
- acceptedEvents
- .filter(pb => awardees.has(pb.pubkey))
- .filter(pb => pb.tags.find(t => t.at(0) === "a" && t.at(1) === address))
- .map(pb => pb.pubkey),
- );
- const thumb = findTag(e, "thumb");
- const image = findTag(e, "image");
- return { name, thumb, image, awardees, accepted };
- });
- return [];
- }, [rawBadges]);
-
- return { badges, awards: badgeAwards };
+ const awards = useRequestBuilder(subBadgeAwards);
+ return {
+ awards: awards.map(
+ a =>
+ ({
+ event: a,
+ awardees: new Set(a.tags.filter(b => b[0] === "p").map(b => b[1])),
+ }) as BadgeAward,
+ ),
+ };
+}
+
+export function useProfileBadges(pubkey: string) {
+ const sub = new RequestBuilder(`profile-badges:${pubkey}`);
+ sub.withFilter().kinds([EventKind.ProfileBadges]).authors([pubkey]).tag("d", ["profile_badges"]);
+ const data = useRequestBuilder(sub).at(0);
+ return {
+ event: data,
+ isAccepted: (link: NostrLink) => {
+ if (!data) return false;
+ const links = NostrLink.fromAllTags(data.tags);
+ return links.some(a => a.equals(link));
+ },
+ };
}
diff --git a/src/types.ts b/src/types.ts
index bc6f3ff..8508c12 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -24,11 +24,3 @@ export interface EmojiPack {
author: string;
emojis: EmojiTag[];
}
-
-export interface Badge {
- name: string;
- thumb?: string;
- image?: string;
- awardees: Set;
- accepted: Set;
-}