mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-05 10:11:12 +02:00
feat: fav repos and git author lists
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Bookmark, FileText, Link } from "lucide-react";
|
||||
import { getTagValues } from "@/lib/nostr-utils";
|
||||
import {
|
||||
getEventPointerFromETag,
|
||||
getAddressPointerFromATag,
|
||||
} from "applesauce-core/helpers";
|
||||
getTagValues,
|
||||
getEventPointers,
|
||||
getAddressPointers,
|
||||
} from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -11,39 +11,6 @@ import {
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull, UrlListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer, AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags
|
||||
*/
|
||||
function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract address pointers from a tags
|
||||
*/
|
||||
function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10003 Renderer - Bookmark List (Feed View)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Bookmark, FileText, Link } from "lucide-react";
|
||||
import { getTagValue } from "applesauce-core/helpers";
|
||||
import { getTagValues } from "@/lib/nostr-utils";
|
||||
import {
|
||||
getEventPointerFromETag,
|
||||
getAddressPointerFromATag,
|
||||
} from "applesauce-core/helpers";
|
||||
getTagValues,
|
||||
getEventPointers,
|
||||
getAddressPointers,
|
||||
} from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -12,39 +12,6 @@ import {
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull, UrlListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer, AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags
|
||||
*/
|
||||
function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract address pointers from a tags
|
||||
*/
|
||||
function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 30003 Renderer - Bookmark Set (Feed View)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { MessageCircle, Hash } from "lucide-react";
|
||||
import { getEventPointerFromETag } from "applesauce-core/helpers";
|
||||
import { getEventPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -7,24 +7,6 @@ import {
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags (for channel references)
|
||||
* Channels are kind 40 events
|
||||
*/
|
||||
function getChannelPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10005 Renderer - Public Chats List (Feed View)
|
||||
@@ -32,7 +14,7 @@ function getChannelPointers(event: NostrEvent): EventPointer[] {
|
||||
* Note: This is different from kind 10009 which is for NIP-29 groups
|
||||
*/
|
||||
export function ChannelListRenderer({ event }: BaseEventProps) {
|
||||
const channels = getChannelPointers(event);
|
||||
const channels = getEventPointers(event);
|
||||
|
||||
if (channels.length === 0) {
|
||||
return (
|
||||
@@ -66,7 +48,7 @@ export function ChannelListRenderer({ event }: BaseEventProps) {
|
||||
* Kind 10005 Detail View - Full channel list
|
||||
*/
|
||||
export function ChannelListDetailRenderer({ event }: { event: NostrEvent }) {
|
||||
const channels = getChannelPointers(event);
|
||||
const channels = getEventPointers(event);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 p-4">
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Library, FileText, Video, Image } from "lucide-react";
|
||||
import { getTagValue } from "applesauce-core/helpers";
|
||||
import {
|
||||
getEventPointerFromETag,
|
||||
getAddressPointerFromATag,
|
||||
} from "applesauce-core/helpers";
|
||||
import { getEventPointers, getAddressPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -11,39 +8,6 @@ import {
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer, AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags
|
||||
*/
|
||||
function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract address pointers from a tags
|
||||
*/
|
||||
function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
interface CurationSetRendererProps extends BaseEventProps {
|
||||
/** Icon to display */
|
||||
|
||||
116
src/components/nostr/kinds/FavoriteReposRenderer.tsx
Normal file
116
src/components/nostr/kinds/FavoriteReposRenderer.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import { FolderGit2, GitBranch } from "lucide-react";
|
||||
import { getAddressPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
ClickableEventTitle,
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull } from "../lists";
|
||||
import { useNostrEvent } from "@/hooks/useNostrEvent";
|
||||
import { useAddWindow } from "@/core/state";
|
||||
import { getRepositoryName } from "@/lib/nip34-helpers";
|
||||
import { getReplaceableIdentifier } from "applesauce-core/helpers";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Clickable repo name that loads and displays the repository name
|
||||
*/
|
||||
function RepoNameItem({ pointer }: { pointer: AddressPointer }) {
|
||||
const event = useNostrEvent(pointer);
|
||||
const addWindow = useAddWindow();
|
||||
|
||||
const displayName = event
|
||||
? getRepositoryName(event) ||
|
||||
getReplaceableIdentifier(event) ||
|
||||
"Repository"
|
||||
: pointer.identifier || "Loading...";
|
||||
|
||||
const handleClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
addWindow("open", { pointer });
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleClick}
|
||||
className="flex items-center gap-1.5 text-xs text-foreground hover:text-foreground cursor-crosshair transition-colors"
|
||||
>
|
||||
<GitBranch className="size-3.5 flex-shrink-0 text-muted-foreground" />
|
||||
<span className="hover:underline hover:decoration-dotted truncate">
|
||||
{displayName}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10018 Renderer - Favorite Repositories (Feed View)
|
||||
*/
|
||||
export function FavoriteReposRenderer({ event }: BaseEventProps) {
|
||||
const pointers = getAddressPointers(event).filter((p) => p.kind === 30617);
|
||||
|
||||
if (pointers.length === 0) {
|
||||
return (
|
||||
<BaseEventContainer event={event}>
|
||||
<div className="text-xs text-muted-foreground italic">
|
||||
No favorite repositories
|
||||
</div>
|
||||
</BaseEventContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BaseEventContainer event={event}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<ClickableEventTitle
|
||||
event={event}
|
||||
className="flex items-center gap-1.5 text-sm font-medium"
|
||||
>
|
||||
<FolderGit2 className="size-4 text-muted-foreground" />
|
||||
<span>Favorite Repositories ({pointers.length})</span>
|
||||
</ClickableEventTitle>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
{pointers.map((pointer) => (
|
||||
<RepoNameItem
|
||||
key={`${pointer.kind}:${pointer.pubkey}:${pointer.identifier}`}
|
||||
pointer={pointer}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</BaseEventContainer>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10018 Detail Renderer - Favorite Repositories (Full View)
|
||||
*/
|
||||
export function FavoriteReposDetailRenderer({ event }: { event: NostrEvent }) {
|
||||
const pointers = getAddressPointers(event).filter((p) => p.kind === 30617);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<FolderGit2 className="size-6 text-muted-foreground" />
|
||||
<span className="text-lg font-semibold">Favorite Repositories</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
({pointers.length})
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{pointers.length === 0 ? (
|
||||
<div className="text-sm text-muted-foreground italic">
|
||||
No favorite repositories yet
|
||||
</div>
|
||||
) : (
|
||||
<EventRefListFull
|
||||
addressPointers={pointers}
|
||||
label="Repositories"
|
||||
icon={<GitBranch className="size-5" />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
70
src/components/nostr/kinds/GitAuthorsRenderer.tsx
Normal file
70
src/components/nostr/kinds/GitAuthorsRenderer.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { FileCode, Users } from "lucide-react";
|
||||
import { getTagValues } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
ClickableEventTitle,
|
||||
} from "./BaseEventRenderer";
|
||||
import { PubkeyListPreview, PubkeyListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
|
||||
/**
|
||||
* Kind 10017 Renderer - Git Authors (Feed View)
|
||||
* Follow list of people who produce NIP-34 code events
|
||||
*/
|
||||
export function GitAuthorsRenderer({ event }: BaseEventProps) {
|
||||
const pubkeys = getTagValues(event, "p");
|
||||
|
||||
if (pubkeys.length === 0) {
|
||||
return (
|
||||
<BaseEventContainer event={event}>
|
||||
<div className="text-xs text-muted-foreground italic">
|
||||
No git authors followed
|
||||
</div>
|
||||
</BaseEventContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<BaseEventContainer event={event}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<ClickableEventTitle
|
||||
event={event}
|
||||
className="flex items-center gap-1.5 text-sm font-medium"
|
||||
>
|
||||
<FileCode className="size-4 text-muted-foreground" />
|
||||
<span>Git Authors</span>
|
||||
</ClickableEventTitle>
|
||||
|
||||
<PubkeyListPreview
|
||||
pubkeys={pubkeys}
|
||||
previewLimit={3}
|
||||
label="authors"
|
||||
icon={<Users className="size-4 text-muted-foreground" />}
|
||||
/>
|
||||
</div>
|
||||
</BaseEventContainer>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10017 Detail View - Full git authors list
|
||||
*/
|
||||
export function GitAuthorsDetailRenderer({ event }: { event: NostrEvent }) {
|
||||
const pubkeys = getTagValues(event, "p");
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-6 p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<FileCode className="size-6 text-muted-foreground" />
|
||||
<span className="text-lg font-semibold">Git Authors</span>
|
||||
</div>
|
||||
|
||||
<PubkeyListFull
|
||||
pubkeys={pubkeys}
|
||||
label="Authors"
|
||||
icon={<Users className="size-5" />}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Sparkles } from "lucide-react";
|
||||
import { getTagValue } from "applesauce-core/helpers";
|
||||
import { getTagValues } from "@/lib/nostr-utils";
|
||||
import { getAddressPointerFromATag } from "applesauce-core/helpers";
|
||||
import { getTagValues, getAddressPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -13,23 +12,6 @@ import {
|
||||
EventRefListFull,
|
||||
} from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract address pointers from a tags (for interest sets references)
|
||||
*/
|
||||
function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10015 Renderer - Interest List (Feed View)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { VolumeX, Users, Hash, Type, FileText } from "lucide-react";
|
||||
import { getTagValues } from "@/lib/nostr-utils";
|
||||
import { getEventPointerFromETag } from "applesauce-core/helpers";
|
||||
import { getTagValues, getEventPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -13,23 +12,6 @@ import {
|
||||
EventRefListFull,
|
||||
} from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags
|
||||
*/
|
||||
function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10000 Renderer - Mute List (Feed View)
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Pin, FileText } from "lucide-react";
|
||||
import {
|
||||
getEventPointerFromETag,
|
||||
getAddressPointerFromATag,
|
||||
} from "applesauce-core/helpers";
|
||||
import { getEventPointers, getAddressPointers } from "@/lib/nostr-utils";
|
||||
import {
|
||||
BaseEventProps,
|
||||
BaseEventContainer,
|
||||
@@ -10,39 +7,6 @@ import {
|
||||
} from "./BaseEventRenderer";
|
||||
import { EventRefListFull } from "../lists";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
import type { EventPointer, AddressPointer } from "nostr-tools/nip19";
|
||||
|
||||
/**
|
||||
* Extract event pointers from e tags
|
||||
*/
|
||||
function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract address pointers from a tags
|
||||
*/
|
||||
function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kind 10001 Renderer - Pin List (Feed View)
|
||||
|
||||
@@ -61,7 +61,7 @@ export function RepositoryRenderer({ event }: BaseEventProps) {
|
||||
className="flex items-center gap-1 text-muted-foreground underline decoration-dotted cursor-crosshair line-clamp-1"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Globe className="size-3" />
|
||||
<Globe className="size-3 flex-shrink-0" />
|
||||
<span className="truncate line-clamp-1">{webUrls[0]}</span>
|
||||
</a>
|
||||
)}
|
||||
|
||||
@@ -104,6 +104,14 @@ import {
|
||||
InterestSetRenderer,
|
||||
InterestSetDetailRenderer,
|
||||
} from "./InterestListRenderer";
|
||||
import {
|
||||
FavoriteReposRenderer,
|
||||
FavoriteReposDetailRenderer,
|
||||
} from "./FavoriteReposRenderer";
|
||||
import {
|
||||
GitAuthorsRenderer,
|
||||
GitAuthorsDetailRenderer,
|
||||
} from "./GitAuthorsRenderer";
|
||||
import {
|
||||
MediaFollowListRenderer,
|
||||
MediaFollowListDetailRenderer,
|
||||
@@ -238,6 +246,8 @@ const kindRenderers: Record<number, React.ComponentType<BaseEventProps>> = {
|
||||
10009: PublicChatsRenderer, // User Groups List (NIP-51)
|
||||
10012: GenericRelayListRenderer, // Favorite Relays (NIP-51)
|
||||
10015: InterestListRenderer, // Interest List (NIP-51)
|
||||
10017: GitAuthorsRenderer, // Git Authors (NIP-51)
|
||||
10018: FavoriteReposRenderer, // Favorite Repositories (NIP-51)
|
||||
10020: MediaFollowListRenderer, // Media Follow List (NIP-51)
|
||||
10030: EmojiListRenderer, // User Emoji List (NIP-51)
|
||||
10040: TrustedProviderListRenderer, // Trusted Provider List (NIP-85)
|
||||
@@ -359,6 +369,8 @@ const detailRenderers: Record<
|
||||
10004: CommunityListDetailRenderer, // Community List Detail (NIP-51)
|
||||
10005: ChannelListDetailRenderer, // Channel List Detail (NIP-51)
|
||||
10015: InterestListDetailRenderer, // Interest List Detail (NIP-51)
|
||||
10017: GitAuthorsDetailRenderer, // Git Authors Detail (NIP-34)
|
||||
10018: FavoriteReposDetailRenderer, // Favorite Repositories Detail (NIP-34)
|
||||
10040: TrustedProviderListDetailRenderer, // Trusted Provider List Detail (NIP-85)
|
||||
10020: MediaFollowListDetailRenderer, // Media Follow List Detail (NIP-51)
|
||||
10030: EmojiListDetailRenderer, // User Emoji List Detail (NIP-51)
|
||||
|
||||
@@ -825,6 +825,20 @@ export const EVENT_KINDS: Record<number | string, EventKind> = {
|
||||
nip: "51",
|
||||
icon: Heart,
|
||||
},
|
||||
10017: {
|
||||
kind: 10017,
|
||||
name: "Git Authors",
|
||||
description: "Code follow list (NIP-34 event producers)",
|
||||
nip: "51",
|
||||
icon: FileCode,
|
||||
},
|
||||
10018: {
|
||||
kind: 10018,
|
||||
name: "Favorite Repositories",
|
||||
description: "Favorite git repositories list",
|
||||
nip: "51",
|
||||
icon: FolderGit2,
|
||||
},
|
||||
10019: {
|
||||
kind: 10019,
|
||||
name: "Nutzap Mint Rec",
|
||||
|
||||
@@ -5,6 +5,11 @@ import { getNip10References } from "applesauce-common/helpers/threading";
|
||||
import { getCommentReplyPointer } from "applesauce-common/helpers/comment";
|
||||
import type { EventPointer, AddressPointer } from "nostr-tools/nip19";
|
||||
import { isSafeRelayURL } from "applesauce-core/helpers/relays";
|
||||
import {
|
||||
getEventPointerFromETag,
|
||||
getAddressPointerFromATag,
|
||||
getOrComputeCachedValue,
|
||||
} from "applesauce-core/helpers";
|
||||
|
||||
export function derivePlaceholderName(pubkey: string): string {
|
||||
return `${pubkey.slice(0, 4)}:${pubkey.slice(-4)}`;
|
||||
@@ -63,6 +68,45 @@ export function getTagValues(event: NostrEvent, tagName: string): string[] {
|
||||
.map((tag) => tag[1]);
|
||||
}
|
||||
|
||||
const EventPointersSymbol = Symbol("eventPointers");
|
||||
const AddressPointersSymbol = Symbol("addressPointers");
|
||||
|
||||
/**
|
||||
* Extract all EventPointers from e tags on an event (cached)
|
||||
*/
|
||||
export function getEventPointers(event: NostrEvent): EventPointer[] {
|
||||
return getOrComputeCachedValue(event, EventPointersSymbol, () => {
|
||||
const pointers: EventPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "e" && tag[1]) {
|
||||
const pointer = getEventPointerFromETag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract all AddressPointers from a tags on an event (cached)
|
||||
*/
|
||||
export function getAddressPointers(event: NostrEvent): AddressPointer[] {
|
||||
return getOrComputeCachedValue(event, AddressPointersSymbol, () => {
|
||||
const pointers: AddressPointer[] = [];
|
||||
for (const tag of event.tags) {
|
||||
if (tag[0] === "a" && tag[1]) {
|
||||
const pointer = getAddressPointerFromATag(tag);
|
||||
if (pointer) {
|
||||
pointers.push(pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return pointers;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a q-tag (quote tag) into an EventPointer with relay hints
|
||||
* Q-tag format per NIP-18: ["q", eventId, relayUrl?, pubkey?]
|
||||
|
||||
Reference in New Issue
Block a user