Setup lang
This commit is contained in:
@ -1,11 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import {
|
||||
TaggedNostrEvent,
|
||||
EventKind,
|
||||
NoteCollection,
|
||||
RequestBuilder,
|
||||
} from "@snort/system";
|
||||
import { TaggedNostrEvent, EventKind, NoteCollection, RequestBuilder } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
|
||||
import { findTag, toAddress, getTagValues } from "utils";
|
||||
@ -20,10 +15,7 @@ export function useBadges(
|
||||
const rb = new RequestBuilder(`badges:${pubkey.slice(0, 12)}`);
|
||||
rb.withOptions({ leaveOpen });
|
||||
rb.withFilter().authors([pubkey]).kinds([EventKind.Badge]);
|
||||
rb.withFilter()
|
||||
.authors([pubkey])
|
||||
.kinds([EventKind.BadgeAward])
|
||||
.since(since);
|
||||
rb.withFilter().authors([pubkey]).kinds([EventKind.BadgeAward]).since(since);
|
||||
return rb;
|
||||
}, [pubkey, since]);
|
||||
|
||||
@ -31,15 +23,13 @@ export function useBadges(
|
||||
|
||||
const rawBadges = useMemo(() => {
|
||||
if (badgeEvents) {
|
||||
return badgeEvents
|
||||
.filter((e) => e.kind === EventKind.Badge)
|
||||
.sort((a, b) => b.created_at - a.created_at);
|
||||
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.filter(e => e.kind === EventKind.BadgeAward);
|
||||
}
|
||||
return [];
|
||||
}, [badgeEvents]);
|
||||
@ -47,10 +37,7 @@ export function useBadges(
|
||||
const acceptedSub = useMemo(() => {
|
||||
if (rawBadges.length === 0) return null;
|
||||
const rb = new RequestBuilder(`accepted-badges:${pubkey.slice(0, 12)}`);
|
||||
rb.withFilter()
|
||||
.kinds([EventKind.ProfileBadges])
|
||||
.tag("d", ["profile_badges"])
|
||||
.tag("a", rawBadges.map(toAddress));
|
||||
rb.withFilter().kinds([EventKind.ProfileBadges]).tag("d", ["profile_badges"]).tag("a", rawBadges.map(toAddress));
|
||||
return rb;
|
||||
}, [rawBadges]);
|
||||
|
||||
@ -58,22 +45,16 @@ export function useBadges(
|
||||
const acceptedEvents = acceptedStream.data ?? [];
|
||||
|
||||
const badges = useMemo(() => {
|
||||
return rawBadges.map((e) => {
|
||||
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 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)
|
||||
.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");
|
||||
|
@ -1,49 +1,34 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import {
|
||||
TaggedNostrEvent,
|
||||
ReplaceableNoteStore,
|
||||
NoteCollection,
|
||||
RequestBuilder,
|
||||
} from "@snort/system";
|
||||
import { TaggedNostrEvent, ReplaceableNoteStore, NoteCollection, RequestBuilder } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
|
||||
import { USER_CARDS, CARD } from "const";
|
||||
import { findTag } from "utils";
|
||||
|
||||
export function useUserCards(
|
||||
pubkey: string,
|
||||
userCards: Array<string[]>,
|
||||
leaveOpen = false
|
||||
): TaggedNostrEvent[] {
|
||||
export function useUserCards(pubkey: string, userCards: Array<string[]>, leaveOpen = false): TaggedNostrEvent[] {
|
||||
const related = useMemo(() => {
|
||||
// filtering to only show CARD kinds for now, but in the future we could link and render anything
|
||||
if (userCards?.length > 0) {
|
||||
return userCards.filter(
|
||||
(t) => t.at(0) === "a" && t.at(1)?.startsWith(`${CARD}:`)
|
||||
);
|
||||
return userCards.filter(t => t.at(0) === "a" && t.at(1)?.startsWith(`${CARD}:`));
|
||||
}
|
||||
return [];
|
||||
}, [userCards]);
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const splitted = related.map(t => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(1))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
const identifiers = splitted
|
||||
.map((s) => s.at(2))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(2))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
|
||||
const rb = new RequestBuilder(`cards:${pubkey}`);
|
||||
rb.withOptions({ leaveOpen })
|
||||
.withFilter()
|
||||
.kinds([CARD])
|
||||
.authors(authors)
|
||||
.tag("d", identifiers);
|
||||
rb.withOptions({ leaveOpen }).withFilter().kinds([CARD]).authors(authors).tag("d", identifiers);
|
||||
|
||||
return rb;
|
||||
}, [pubkey, related]);
|
||||
@ -52,27 +37,19 @@ export function useUserCards(
|
||||
|
||||
const cards = useMemo(() => {
|
||||
return related
|
||||
.map((t) => {
|
||||
.map(t => {
|
||||
const [k, pubkey, identifier] = t[1].split(":");
|
||||
const kind = Number(k);
|
||||
return (data ?? []).find(
|
||||
(e) =>
|
||||
e.kind === kind &&
|
||||
e.pubkey === pubkey &&
|
||||
findTag(e, "d") === identifier
|
||||
);
|
||||
return (data ?? []).find(e => e.kind === kind && e.pubkey === pubkey && findTag(e, "d") === identifier);
|
||||
})
|
||||
.filter((e) => e)
|
||||
.map((e) => e as TaggedNostrEvent);
|
||||
.filter(e => e)
|
||||
.map(e => e as TaggedNostrEvent);
|
||||
}, [related, data]);
|
||||
|
||||
return cards;
|
||||
}
|
||||
|
||||
export function useCards(
|
||||
pubkey: string,
|
||||
leaveOpen = false
|
||||
): TaggedNostrEvent[] {
|
||||
export function useCards(pubkey: string, leaveOpen = false): TaggedNostrEvent[] {
|
||||
const sub = useMemo(() => {
|
||||
const b = new RequestBuilder(`user-cards:${pubkey.slice(0, 12)}`);
|
||||
b.withOptions({
|
||||
@ -89,31 +66,25 @@ export function useCards(
|
||||
const related = useMemo(() => {
|
||||
// filtering to only show CARD kinds for now, but in the future we could link and render anything
|
||||
if (userCards) {
|
||||
return userCards.tags.filter(
|
||||
(t) => t.at(0) === "a" && t.at(1)?.startsWith(`${CARD}:`)
|
||||
);
|
||||
return userCards.tags.filter(t => t.at(0) === "a" && t.at(1)?.startsWith(`${CARD}:`));
|
||||
}
|
||||
return [];
|
||||
}, [userCards]);
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const splitted = related.map(t => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(1))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
const identifiers = splitted
|
||||
.map((s) => s.at(2))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(2))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
|
||||
const rb = new RequestBuilder(`cards:${pubkey}`);
|
||||
rb.withOptions({ leaveOpen })
|
||||
.withFilter()
|
||||
.kinds([CARD])
|
||||
.authors(authors)
|
||||
.tag("d", identifiers);
|
||||
rb.withOptions({ leaveOpen }).withFilter().kinds([CARD]).authors(authors).tag("d", identifiers);
|
||||
|
||||
return rb;
|
||||
}, [pubkey, related]);
|
||||
@ -123,18 +94,13 @@ export function useCards(
|
||||
|
||||
const cards = useMemo(() => {
|
||||
return related
|
||||
.map((t) => {
|
||||
.map(t => {
|
||||
const [k, pubkey, identifier] = t[1].split(":");
|
||||
const kind = Number(k);
|
||||
return cardEvents.find(
|
||||
(e) =>
|
||||
e.kind === kind &&
|
||||
e.pubkey === pubkey &&
|
||||
findTag(e, "d") === identifier
|
||||
);
|
||||
return cardEvents.find(e => e.kind === kind && e.pubkey === pubkey && findTag(e, "d") === identifier);
|
||||
})
|
||||
.filter((e) => e)
|
||||
.map((e) => e as TaggedNostrEvent);
|
||||
.filter(e => e)
|
||||
.map(e => e as TaggedNostrEvent);
|
||||
}, [related, cardEvents]);
|
||||
|
||||
return cards;
|
||||
|
@ -1,32 +1,17 @@
|
||||
import { unwrap } from "@snort/shared";
|
||||
import {
|
||||
NostrEvent,
|
||||
NostrLink,
|
||||
NostrPrefix,
|
||||
NoteCollection,
|
||||
RequestBuilder,
|
||||
TaggedNostrEvent,
|
||||
} from "@snort/system";
|
||||
import { NostrEvent, NostrLink, NostrPrefix, NoteCollection, RequestBuilder, TaggedNostrEvent } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { LIVE_STREAM } from "const";
|
||||
import { useMemo } from "react";
|
||||
|
||||
export function useCurrentStreamFeed(
|
||||
link: NostrLink,
|
||||
leaveOpen = false,
|
||||
evPreload?: NostrEvent
|
||||
) {
|
||||
const author =
|
||||
link.type === NostrPrefix.Address ? unwrap(link.author) : link.id;
|
||||
export function useCurrentStreamFeed(link: NostrLink, leaveOpen = false, evPreload?: NostrEvent) {
|
||||
const author = link.type === NostrPrefix.Address ? unwrap(link.author) : link.id;
|
||||
const sub = useMemo(() => {
|
||||
const b = new RequestBuilder(`current-event:${link.id}`);
|
||||
b.withOptions({
|
||||
leaveOpen,
|
||||
});
|
||||
if (
|
||||
link.type === NostrPrefix.PublicKey ||
|
||||
link.type === NostrPrefix.Profile
|
||||
) {
|
||||
if (link.type === NostrPrefix.PublicKey || link.type === NostrPrefix.Profile) {
|
||||
b.withFilter().authors([link.id]).kinds([LIVE_STREAM]).limit(1);
|
||||
b.withFilter().tag("p", [link.id]).kinds([LIVE_STREAM]).limit(1);
|
||||
} else if (link.type === NostrPrefix.Address) {
|
||||
@ -49,12 +34,8 @@ export function useCurrentStreamFeed(
|
||||
|
||||
return useMemo(() => {
|
||||
const hosting = q.data?.filter(
|
||||
(a) =>
|
||||
a.pubkey === author ||
|
||||
a.tags.some((b) => b[0] === "p" && b[1] === author && b[3] === "host")
|
||||
a => a.pubkey === author || a.tags.some(b => b[0] === "p" && b[1] === author && b[3] === "host")
|
||||
);
|
||||
return [...(hosting ?? [])]
|
||||
.sort((a, b) => (b.created_at > a.created_at ? 1 : -1))
|
||||
.at(0);
|
||||
return [...(hosting ?? [])].sort((a, b) => (b.created_at > a.created_at ? 1 : -1)).at(0);
|
||||
}, [q.data]);
|
||||
}
|
||||
|
@ -1,12 +1,7 @@
|
||||
import { useMemo } from "react";
|
||||
import uniqBy from "lodash.uniqby";
|
||||
|
||||
import {
|
||||
RequestBuilder,
|
||||
ReplaceableNoteStore,
|
||||
NoteCollection,
|
||||
NostrEvent,
|
||||
} from "@snort/system";
|
||||
import { RequestBuilder, ReplaceableNoteStore, NoteCollection, NostrEvent } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { findTag } from "utils";
|
||||
import { EMOJI_PACK, USER_EMOJIS } from "const";
|
||||
@ -23,8 +18,8 @@ export function toEmojiPack(ev: NostrEvent): EmojiPack {
|
||||
name: d,
|
||||
author: ev.pubkey,
|
||||
emojis: ev.tags
|
||||
.filter((t) => t.at(0) === "emoji")
|
||||
.map((t) => ["emoji", cleanShortcode(t.at(1)), t.at(2)]) as EmojiTag[],
|
||||
.filter(t => t.at(0) === "emoji")
|
||||
.map(t => ["emoji", cleanShortcode(t.at(1)), t.at(2)]) as EmojiTag[],
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,24 +30,22 @@ export function packId(pack: EmojiPack): string {
|
||||
export function useUserEmojiPacks(pubkey?: string, userEmoji?: Tags) {
|
||||
const related = useMemo(() => {
|
||||
if (userEmoji) {
|
||||
return userEmoji?.filter(
|
||||
(t) => t.at(0) === "a" && t.at(1)?.startsWith(`${EMOJI_PACK}:`)
|
||||
);
|
||||
return userEmoji?.filter(t => t.at(0) === "a" && t.at(1)?.startsWith(`${EMOJI_PACK}:`));
|
||||
}
|
||||
return [];
|
||||
}, [userEmoji]);
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const splitted = related.map(t => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(1))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
const identifiers = splitted
|
||||
.map((s) => s.at(2))
|
||||
.filter((s) => s)
|
||||
.map((s) => s as string);
|
||||
.map(s => s.at(2))
|
||||
.filter(s => s)
|
||||
.map(s => s as string);
|
||||
|
||||
const rb = new RequestBuilder(`emoji-related:${pubkey}`);
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
NostrPrefix,
|
||||
RequestBuilder,
|
||||
ReplaceableNoteStore,
|
||||
NostrLink,
|
||||
} from "@snort/system";
|
||||
import { NostrPrefix, RequestBuilder, ReplaceableNoteStore, NostrLink } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
|
||||
export default function useEventFeed(link: NostrLink, leaveOpen = false) {
|
||||
@ -24,7 +19,7 @@ export default function useEventFeed(link: NostrLink, leaveOpen = false) {
|
||||
} else {
|
||||
const f = b.withFilter().ids([link.id]);
|
||||
if (link.relays) {
|
||||
link.relays.slice(0, 2).forEach((r) => f.relay(r));
|
||||
link.relays.slice(0, 2).forEach(r => f.relay(r));
|
||||
}
|
||||
if (link.author) {
|
||||
f.authors([link.author]);
|
||||
|
@ -1,11 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import {
|
||||
NostrPrefix,
|
||||
ReplaceableNoteStore,
|
||||
RequestBuilder,
|
||||
type NostrLink,
|
||||
} from "@snort/system";
|
||||
import { NostrPrefix, ReplaceableNoteStore, RequestBuilder, type NostrLink } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
|
||||
export function useAddress(kind: number, pubkey: string, identifier: string) {
|
||||
@ -34,7 +29,7 @@ export function useEvent(link: NostrLink) {
|
||||
} else {
|
||||
const f = b.withFilter().ids([link.id]);
|
||||
if (link.relays) {
|
||||
link.relays.slice(0, 2).forEach((r) => f.relay(r));
|
||||
link.relays.slice(0, 2).forEach(r => f.relay(r));
|
||||
}
|
||||
if (link.author) {
|
||||
f.authors([link.author]);
|
||||
|
@ -17,20 +17,13 @@ export function useZaps(goal: NostrEvent, leaveOpen = false) {
|
||||
const sub = useMemo(() => {
|
||||
const b = new RequestBuilder(`goal-zaps:${goal.id.slice(0, 12)}`);
|
||||
b.withOptions({ leaveOpen });
|
||||
b.withFilter()
|
||||
.kinds([EventKind.ZapReceipt])
|
||||
.tag("e", [goal.id])
|
||||
.since(goal.created_at);
|
||||
b.withFilter().kinds([EventKind.ZapReceipt]).tag("e", [goal.id]).since(goal.created_at);
|
||||
return b;
|
||||
}, [goal, leaveOpen]);
|
||||
|
||||
const { data } = useRequestBuilder(NoteCollection, sub);
|
||||
|
||||
return (
|
||||
data
|
||||
?.map((ev) => parseZap(ev, System.ProfileLoader.Cache))
|
||||
.filter((z) => z && z.valid) ?? []
|
||||
);
|
||||
return data?.map(ev => parseZap(ev, System.ProfileLoader.Cache)).filter(z => z && z.valid) ?? [];
|
||||
}
|
||||
|
||||
export function useZapGoal(host: string, link?: NostrLink, leaveOpen = false) {
|
||||
|
@ -1,9 +1,4 @@
|
||||
import {
|
||||
NostrLink,
|
||||
RequestBuilder,
|
||||
EventKind,
|
||||
NoteCollection,
|
||||
} from "@snort/system";
|
||||
import { NostrLink, RequestBuilder, EventKind, NoteCollection } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { unixNow } from "@snort/shared";
|
||||
import { useMemo } from "react";
|
||||
@ -29,14 +24,14 @@ export function useLiveChatFeed(link: NostrLink, eZaps?: Array<string>) {
|
||||
const feed = useRequestBuilder(NoteCollection, sub);
|
||||
|
||||
const messages = useMemo(() => {
|
||||
return (feed.data ?? []).filter((ev) => ev.kind === LIVE_STREAM_CHAT);
|
||||
return (feed.data ?? []).filter(ev => ev.kind === LIVE_STREAM_CHAT);
|
||||
}, [feed.data]);
|
||||
const zaps = useMemo(() => {
|
||||
return (feed.data ?? []).filter((ev) => ev.kind === EventKind.ZapReceipt);
|
||||
return (feed.data ?? []).filter(ev => ev.kind === EventKind.ZapReceipt);
|
||||
}, [feed.data]);
|
||||
|
||||
const etags = useMemo(() => {
|
||||
return messages.map((e) => e.id);
|
||||
return messages.map(e => e.id);
|
||||
}, [messages]);
|
||||
|
||||
const esub = useMemo(() => {
|
||||
@ -45,9 +40,7 @@ export function useLiveChatFeed(link: NostrLink, eZaps?: Array<string>) {
|
||||
rb.withOptions({
|
||||
leaveOpen: true,
|
||||
});
|
||||
rb.withFilter()
|
||||
.kinds([EventKind.Reaction, EventKind.ZapReceipt])
|
||||
.tag("e", etags);
|
||||
rb.withFilter().kinds([EventKind.Reaction, EventKind.ZapReceipt]).tag("e", etags);
|
||||
return rb;
|
||||
}, [etags]);
|
||||
|
||||
|
@ -38,26 +38,18 @@ export function useStreamsFeed(tag?: string) {
|
||||
const feedSorted = useMemo(() => {
|
||||
if (feed.data) {
|
||||
if (__XXX) {
|
||||
return [...feed.data].filter(
|
||||
(a) => findTag(a, "content-warning") !== undefined
|
||||
);
|
||||
return [...feed.data].filter(a => findTag(a, "content-warning") !== undefined);
|
||||
} else {
|
||||
return [...feed.data].filter(
|
||||
(a) => findTag(a, "content-warning") === undefined
|
||||
);
|
||||
return [...feed.data].filter(a => findTag(a, "content-warning") === undefined);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}, [feed.data]);
|
||||
|
||||
const live = feedSorted
|
||||
.filter((a) => findTag(a, "status") === StreamState.Live)
|
||||
.sort(sortStarts);
|
||||
const planned = feedSorted
|
||||
.filter((a) => findTag(a, "status") === StreamState.Planned)
|
||||
.sort(sortStarts);
|
||||
const live = feedSorted.filter(a => findTag(a, "status") === StreamState.Live).sort(sortStarts);
|
||||
const planned = feedSorted.filter(a => findTag(a, "status") === StreamState.Planned).sort(sortStarts);
|
||||
const ended = feedSorted
|
||||
.filter((a) => {
|
||||
.filter(a => {
|
||||
const hasEnded = findTag(a, "status") === StreamState.Ended;
|
||||
const recording = findTag(a, "recording") ?? "";
|
||||
return hasEnded && recording?.length > 0;
|
||||
|
@ -11,7 +11,7 @@ import { Login } from "index";
|
||||
|
||||
export function useLogin() {
|
||||
const session = useSyncExternalStore(
|
||||
(c) => Login.hook(c),
|
||||
c => Login.hook(c),
|
||||
() => Login.snapshot()
|
||||
);
|
||||
if (!session) return;
|
||||
@ -26,7 +26,7 @@ export function useLogin() {
|
||||
export function useLoginEvents(pubkey?: string, leaveOpen = false) {
|
||||
const [userEmojis, setUserEmojis] = useState<Tags>([]);
|
||||
const session = useSyncExternalStore(
|
||||
(c) => Login.hook(c),
|
||||
c => Login.hook(c),
|
||||
() => Login.snapshot()
|
||||
);
|
||||
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
export default function usePlaceholder(pubkey: string) {
|
||||
const url = useMemo(
|
||||
() => `https://robohash.v0l.io/${pubkey}.png?set=2`,
|
||||
[pubkey]
|
||||
);
|
||||
const url = useMemo(() => `https://robohash.v0l.io/${pubkey}.png?set=2`, [pubkey]);
|
||||
return url;
|
||||
}
|
||||
|
@ -1,11 +1,5 @@
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
RequestBuilder,
|
||||
NoteCollection,
|
||||
NostrLink,
|
||||
EventKind,
|
||||
parseZap,
|
||||
} from "@snort/system";
|
||||
import { RequestBuilder, NoteCollection, NostrLink, EventKind, parseZap } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { LIVE_STREAM } from "const";
|
||||
import { findTag } from "utils";
|
||||
@ -31,7 +25,7 @@ export function useProfile(link: NostrLink, leaveOpen = false) {
|
||||
|
||||
const addresses = useMemo(() => {
|
||||
if (streamsData) {
|
||||
return streamsData.map((e) => `${e.kind}:${e.pubkey}:${findTag(e, "d")}`);
|
||||
return streamsData.map(e => `${e.kind}:${e.pubkey}:${findTag(e, "d")}`);
|
||||
}
|
||||
return [];
|
||||
}, [streamsData]);
|
||||
@ -49,8 +43,8 @@ export function useProfile(link: NostrLink, leaveOpen = false) {
|
||||
|
||||
const { data: zapsData } = useRequestBuilder(NoteCollection, zapsSub);
|
||||
const zaps = (zapsData ?? [])
|
||||
.map((ev) => parseZap(ev, System.ProfileLoader.Cache))
|
||||
.filter((z) => z && z.valid && z.receiver === link.id);
|
||||
.map(ev => parseZap(ev, System.ProfileLoader.Cache))
|
||||
.filter(z => z && z.valid && z.receiver === link.id);
|
||||
|
||||
const sortedStreams = useMemo(() => {
|
||||
const sorted = [...streams];
|
||||
|
@ -3,7 +3,7 @@ import { useSyncExternalStore } from "react";
|
||||
|
||||
export function useStreamProvider() {
|
||||
return useSyncExternalStore(
|
||||
(c) => StreamProviderStore.hook(c),
|
||||
c => StreamProviderStore.hook(c),
|
||||
() => StreamProviderStore.snapshot()
|
||||
);
|
||||
}
|
||||
|
@ -2,19 +2,15 @@ import { useMemo } from "react";
|
||||
import { ParsedZap } from "@snort/system";
|
||||
|
||||
function totalZapped(pubkey: string, zaps: ParsedZap[]) {
|
||||
return zaps
|
||||
.filter((z) => (z.anonZap ? pubkey === "anon" : z.sender === pubkey))
|
||||
.reduce((acc, z) => acc + z.amount, 0);
|
||||
return zaps.filter(z => (z.anonZap ? pubkey === "anon" : z.sender === pubkey)).reduce((acc, z) => acc + z.amount, 0);
|
||||
}
|
||||
|
||||
export default function useTopZappers(zaps: ParsedZap[]) {
|
||||
const zappers = zaps
|
||||
.map((z) => (z.anonZap ? "anon" : z.sender))
|
||||
.map((p) => p as string);
|
||||
const zappers = zaps.map(z => (z.anonZap ? "anon" : z.sender)).map(p => p as string);
|
||||
|
||||
const sorted = useMemo(() => {
|
||||
const pubkeys = [...new Set([...zappers])];
|
||||
const result = pubkeys.map((pubkey) => {
|
||||
const result = pubkeys.map(pubkey => {
|
||||
return { pubkey, total: totalZapped(pubkey, zaps) };
|
||||
});
|
||||
result.sort((a, b) => b.total - a.total);
|
||||
|
Reference in New Issue
Block a user