forked from Kieran/snort
feat: add useEventReactions to system-react
This commit is contained in:
parent
3b427338f4
commit
5e42c5e70c
@ -1,49 +0,0 @@
|
|||||||
import { EventKind, NostrLink, parseZap, TaggedNostrEvent } from "@snort/system";
|
|
||||||
import { UserCache } from "Cache";
|
|
||||||
import { useMemo } from "react";
|
|
||||||
import { dedupeByPubkey, getLinkReactions, normalizeReaction, Reaction } from "SnortUtils";
|
|
||||||
|
|
||||||
export function useEventReactions(ev: TaggedNostrEvent, related: ReadonlyArray<TaggedNostrEvent>) {
|
|
||||||
return useMemo(() => {
|
|
||||||
const link = NostrLink.fromEvent(ev);
|
|
||||||
const deletions = getLinkReactions(related, link, EventKind.Deletion);
|
|
||||||
const reactions = getLinkReactions(related, link, EventKind.Reaction);
|
|
||||||
const reposts = getLinkReactions(related, link, EventKind.Repost);
|
|
||||||
|
|
||||||
const groupReactions = (() => {
|
|
||||||
const result = reactions?.reduce(
|
|
||||||
(acc, reaction) => {
|
|
||||||
const kind = normalizeReaction(reaction.content);
|
|
||||||
const rs = acc[kind] || [];
|
|
||||||
return { ...acc, [kind]: [...rs, reaction] };
|
|
||||||
},
|
|
||||||
{
|
|
||||||
[Reaction.Positive]: [] as TaggedNostrEvent[],
|
|
||||||
[Reaction.Negative]: [] as TaggedNostrEvent[],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
[Reaction.Positive]: dedupeByPubkey(result[Reaction.Positive]),
|
|
||||||
[Reaction.Negative]: dedupeByPubkey(result[Reaction.Negative]),
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
const positive = groupReactions[Reaction.Positive];
|
|
||||||
const negative = groupReactions[Reaction.Negative];
|
|
||||||
|
|
||||||
const zaps = getLinkReactions(related, link, EventKind.ZapReceipt)
|
|
||||||
.map(a => parseZap(a, UserCache, ev))
|
|
||||||
.filter(a => a.valid)
|
|
||||||
.sort((a, b) => b.amount - a.amount);
|
|
||||||
|
|
||||||
return {
|
|
||||||
deletions,
|
|
||||||
reactions: {
|
|
||||||
all: reactions,
|
|
||||||
positive,
|
|
||||||
negative,
|
|
||||||
},
|
|
||||||
reposts,
|
|
||||||
zaps,
|
|
||||||
};
|
|
||||||
}, [ev, related]);
|
|
||||||
}
|
|
@ -140,29 +140,6 @@ export function hexToBech32(hrp: string, hex?: string) {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reaction types
|
|
||||||
*/
|
|
||||||
export const Reaction = {
|
|
||||||
Positive: "+",
|
|
||||||
Negative: "-",
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return normalized reaction content
|
|
||||||
*/
|
|
||||||
export function normalizeReaction(content: string) {
|
|
||||||
switch (content) {
|
|
||||||
case "-":
|
|
||||||
return Reaction.Negative;
|
|
||||||
case "👎":
|
|
||||||
return Reaction.Negative;
|
|
||||||
default:
|
|
||||||
return Reaction.Positive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getLinkReactions(
|
export function getLinkReactions(
|
||||||
notes: ReadonlyArray<TaggedNostrEvent> | undefined,
|
notes: ReadonlyArray<TaggedNostrEvent> | undefined,
|
||||||
link: NostrLink,
|
link: NostrLink,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@snort/shared",
|
"name": "@snort/shared",
|
||||||
"version": "1.0.7",
|
"version": "1.0.8",
|
||||||
"description": "Shared components for Snort",
|
"description": "Shared components for Snort",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
@ -193,3 +193,25 @@ export async function fetchNip05Pubkey(name: string, domain: string, timeout = 2
|
|||||||
export function removeUndefined<T>(v: Array<T | undefined>) {
|
export function removeUndefined<T>(v: Array<T | undefined>) {
|
||||||
return v.filter(a => a != undefined).map(a => unwrap(a));
|
return v.filter(a => a != undefined).map(a => unwrap(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reaction types
|
||||||
|
*/
|
||||||
|
export const enum Reaction {
|
||||||
|
Positive = "+",
|
||||||
|
Negative = "-",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return normalized reaction content
|
||||||
|
*/
|
||||||
|
export function normalizeReaction(content: string) {
|
||||||
|
switch (content) {
|
||||||
|
case "-":
|
||||||
|
return Reaction.Negative;
|
||||||
|
case "👎":
|
||||||
|
return Reaction.Negative;
|
||||||
|
default:
|
||||||
|
return Reaction.Positive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@snort/system-react",
|
"name": "@snort/system-react",
|
||||||
"version": "1.0.16",
|
"version": "1.0.17",
|
||||||
"description": "React hooks for @snort/system",
|
"description": "React hooks for @snort/system",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
@ -15,7 +15,7 @@
|
|||||||
"dist"
|
"dist"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@snort/shared": "^1.0.7",
|
"@snort/shared": "^1.0.8",
|
||||||
"@snort/system": "^1.0.22",
|
"@snort/system": "^1.0.22",
|
||||||
"react": "^18.2.0"
|
"react": "^18.2.0"
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
export * from "./context";
|
||||||
|
|
||||||
export * from "./useRequestBuilder";
|
export * from "./useRequestBuilder";
|
||||||
export * from "./useSystemState";
|
export * from "./useSystemState";
|
||||||
export * from "./useUserProfile";
|
export * from "./useUserProfile";
|
||||||
export * from "./context";
|
|
||||||
export * from "./useUserSearch";
|
export * from "./useUserSearch";
|
||||||
|
export * from "./useEventReactions";
|
55
packages/system-react/src/useEventReactions.tsx
Normal file
55
packages/system-react/src/useEventReactions.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useContext, useMemo } from "react";
|
||||||
|
import { normalizeReaction, Reaction } from "@snort/shared";
|
||||||
|
import { EventKind, NostrLink, parseZap, TaggedNostrEvent } from "@snort/system";
|
||||||
|
|
||||||
|
import { SnortContext } from "./context";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse reactions to a given event from a set of related events
|
||||||
|
* @param ev
|
||||||
|
* @param related
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function useEventReactions(ev: TaggedNostrEvent, related: ReadonlyArray<TaggedNostrEvent>) {
|
||||||
|
const system = useContext(SnortContext);
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
const link = NostrLink.fromEvent(ev);
|
||||||
|
const reactionKinds = related.reduce((acc, v) => {
|
||||||
|
if (link.isReplyToThis(v)) {
|
||||||
|
acc[v.kind.toString()] ??= [];
|
||||||
|
acc[v.kind.toString()].push(v);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, Array<TaggedNostrEvent>>);
|
||||||
|
|
||||||
|
const deletions = reactionKinds[EventKind.Deletion.toString()] ?? [];
|
||||||
|
const reactions = reactionKinds[EventKind.Reaction.toString()] ?? [];
|
||||||
|
const reposts = reactionKinds[EventKind.Repost.toString()] ?? [];
|
||||||
|
|
||||||
|
const groupReactions = reactions?.reduce((acc, reaction) => {
|
||||||
|
const kind = normalizeReaction(reaction.content);
|
||||||
|
acc[kind] ??= [];
|
||||||
|
acc[kind].push(reaction);
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<Reaction, Array<TaggedNostrEvent>>);
|
||||||
|
|
||||||
|
const zaps = (reactionKinds[EventKind.ZapReceipt] ?? [])
|
||||||
|
.map(a => parseZap(a, system.ProfileLoader.Cache, ev))
|
||||||
|
.filter(a => a.valid)
|
||||||
|
.sort((a, b) => b.amount - a.amount);
|
||||||
|
|
||||||
|
return {
|
||||||
|
deletions,
|
||||||
|
reactions: {
|
||||||
|
positive: groupReactions[Reaction.Positive],
|
||||||
|
negative: groupReactions[Reaction.Negative],
|
||||||
|
},
|
||||||
|
reposts,
|
||||||
|
zaps,
|
||||||
|
others: Object.fromEntries(
|
||||||
|
Object.entries(reactionKinds)
|
||||||
|
.filter(([k]) => ![EventKind.Deletion, EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt].includes(Number(k))))
|
||||||
|
};
|
||||||
|
}, [ev, related]);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user