mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-06-15 00:58:44 +02:00
fix: correct API usage for EventFactory and NostrEvent types
## ComposeDialog - Fix useProfile import (from @/hooks/useProfile, not applesauce-react) - Use hub.factory.build() and hub.factory.sign() instead of hub.run() - Remove unused EventFactory type import ## RelaySelector - Simplify to not require relay pool stats (not available in API) - Remove connection status indicators (Wifi/WifiOff icons) - Show selected relays only, with add/remove functionality - Removed unused RelayItem component ## thread-builder - Import getSeenRelays helper for relay hints - Replace event.relay (doesn't exist on NostrEvent) with getSeenRelays() - Use first seen relay as relay hint in tags - Remove references.mentions usage (property doesn't exist) All API calls now match actual types and available methods.
This commit is contained in:
@@ -24,10 +24,9 @@ import type { NostrEvent } from "nostr-tools/core";
|
||||
import { relayListCache } from "@/services/relay-list-cache";
|
||||
import { Send, Eye, Edit3, AtSign, X } from "lucide-react";
|
||||
import { getDisplayName } from "@/lib/nostr-utils";
|
||||
import { useProfile } from "applesauce-react/hooks";
|
||||
import { useProfile } from "@/hooks/useProfile";
|
||||
import { RelaySelector } from "@/components/RelaySelector";
|
||||
import { PowerTools } from "@/components/PowerTools";
|
||||
import type { EventFactory } from "applesauce-core/event-factory";
|
||||
|
||||
export interface ComposeDialogProps {
|
||||
/** Whether dialog is open */
|
||||
@@ -140,13 +139,12 @@ export function ComposeDialog({
|
||||
}
|
||||
|
||||
// Create and sign event
|
||||
const event = await hub.run(
|
||||
async ({ factory }: { factory: EventFactory }) => {
|
||||
const unsigned = factory.event(kind, messageContent, tags);
|
||||
const signed = await factory.sign(unsigned);
|
||||
return signed;
|
||||
},
|
||||
);
|
||||
const draft = await hub.factory.build({
|
||||
kind,
|
||||
content: messageContent,
|
||||
tags,
|
||||
});
|
||||
const event = await hub.factory.sign(draft);
|
||||
|
||||
// Publish to selected relays
|
||||
await publishEventToRelays(event, selectedRelays);
|
||||
|
||||
@@ -7,10 +7,8 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/components/ui/popover";
|
||||
import { X, Plus, Wifi, WifiOff, Settings2 } from "lucide-react";
|
||||
import { X, Plus, Settings2 } from "lucide-react";
|
||||
import { normalizeURL } from "applesauce-core/helpers";
|
||||
import pool from "@/services/relay-pool";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
|
||||
export interface RelaySelectorProps {
|
||||
/** Currently selected relays */
|
||||
@@ -38,9 +36,6 @@ export function RelaySelector({
|
||||
const [newRelayUrl, setNewRelayUrl] = useState("");
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
// Get relay pool stats
|
||||
const relayStats = use$(pool.stats$) || new Map();
|
||||
|
||||
// Handle add relay
|
||||
const handleAddRelay = useCallback(() => {
|
||||
if (!newRelayUrl.trim()) return;
|
||||
@@ -89,23 +84,6 @@ export function RelaySelector({
|
||||
[selectedRelays, handleRemoveRelay, onRelaysChange, maxRelays],
|
||||
);
|
||||
|
||||
// Get relay connection status
|
||||
const getRelayStatus = useCallback(
|
||||
(relay: string): "connected" | "connecting" | "disconnected" => {
|
||||
const stats = relayStats.get(relay);
|
||||
if (!stats) return "disconnected";
|
||||
|
||||
// Check if there are any active subscriptions
|
||||
if (stats.connectionState === "open") return "connected";
|
||||
if (stats.connectionState === "connecting") return "connecting";
|
||||
return "disconnected";
|
||||
},
|
||||
[relayStats],
|
||||
);
|
||||
|
||||
// Get all known relays from pool
|
||||
const knownRelays: string[] = Array.from(relayStats.keys()) as string[];
|
||||
|
||||
return (
|
||||
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
@@ -125,54 +103,33 @@ export function RelaySelector({
|
||||
</div>
|
||||
|
||||
{/* Selected Relays */}
|
||||
{selectedRelays.length > 0 && (
|
||||
<div className="p-4 border-b bg-muted/30">
|
||||
<div className="text-xs font-medium mb-2 text-muted-foreground">
|
||||
SELECTED ({selectedRelays.length})
|
||||
</div>
|
||||
<ScrollArea className="flex-1 p-4">
|
||||
{selectedRelays.length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
{selectedRelays.map((relay: string) => (
|
||||
<RelayItem
|
||||
<div
|
||||
key={relay}
|
||||
relay={relay}
|
||||
status={getRelayStatus(relay)}
|
||||
selected={true}
|
||||
onToggle={() => {
|
||||
handleRemoveRelay(relay);
|
||||
}}
|
||||
/>
|
||||
className="flex items-center gap-2 p-2 rounded-md bg-muted/50"
|
||||
>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-mono truncate">{relay}</div>
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-6 w-6 flex-shrink-0 hover:bg-destructive/10 hover:text-destructive"
|
||||
onClick={() => handleRemoveRelay(relay)}
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Available Relays */}
|
||||
<ScrollArea className="flex-1 p-4">
|
||||
<div className="space-y-2">
|
||||
<div className="text-xs font-medium mb-2 text-muted-foreground">
|
||||
AVAILABLE
|
||||
) : (
|
||||
<div className="text-sm text-muted-foreground italic py-4 text-center">
|
||||
No relays selected. Add relays below.
|
||||
</div>
|
||||
{knownRelays
|
||||
.filter((relay: string) => !selectedRelays.includes(relay))
|
||||
.map((relay: string) => (
|
||||
<RelayItem
|
||||
key={relay}
|
||||
relay={relay}
|
||||
status={getRelayStatus(relay)}
|
||||
selected={false}
|
||||
onToggle={() => {
|
||||
handleToggleRelay(relay);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{knownRelays.filter((r: string) => !selectedRelays.includes(r))
|
||||
.length === 0 && (
|
||||
<div className="text-sm text-muted-foreground italic py-4 text-center">
|
||||
No other relays available
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</ScrollArea>
|
||||
|
||||
{/* Add Relay */}
|
||||
@@ -205,60 +162,3 @@ export function RelaySelector({
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Individual relay item
|
||||
*/
|
||||
function RelayItem({
|
||||
relay,
|
||||
status,
|
||||
selected,
|
||||
onToggle,
|
||||
}: {
|
||||
relay: string;
|
||||
status: "connected" | "connecting" | "disconnected";
|
||||
selected: boolean;
|
||||
onToggle: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center gap-2 p-2 rounded-md hover:bg-muted/50 transition-colors cursor-pointer"
|
||||
onClick={onToggle}
|
||||
>
|
||||
{/* Status Indicator */}
|
||||
{status === "connected" && (
|
||||
<Wifi className="w-4 h-4 text-green-500 flex-shrink-0" />
|
||||
)}
|
||||
{status === "connecting" && (
|
||||
<Wifi className="w-4 h-4 text-yellow-500 flex-shrink-0 animate-pulse" />
|
||||
)}
|
||||
{status === "disconnected" && (
|
||||
<WifiOff className="w-4 h-4 text-muted-foreground flex-shrink-0" />
|
||||
)}
|
||||
|
||||
{/* Relay URL */}
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-mono truncate">{relay}</div>
|
||||
</div>
|
||||
|
||||
{/* Selection Indicator */}
|
||||
{selected ? (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-6 w-6 flex-shrink-0 hover:bg-destructive/10 hover:text-destructive"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-6 w-6 flex-shrink-0 hover:bg-primary/10"
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { NostrEvent } from "nostr-tools/core";
|
||||
import { getNip10References } from "applesauce-common/helpers/threading";
|
||||
import { getSeenRelays } from "applesauce-core/helpers/relays";
|
||||
|
||||
/**
|
||||
* Thread tags for an event reply
|
||||
@@ -29,28 +30,34 @@ export function buildNip10Tags(
|
||||
const tags: string[][] = [];
|
||||
const references = getNip10References(replyTo);
|
||||
|
||||
// Get relay hint from where event was seen
|
||||
const seenRelaysSet = getSeenRelays(replyTo);
|
||||
const relayHint = seenRelaysSet ? Array.from(seenRelaysSet)[0] : undefined;
|
||||
|
||||
// Add root tag
|
||||
if (references.root) {
|
||||
const root = references.root.e || references.root.a;
|
||||
if (root && "id" in root) {
|
||||
// EventPointer
|
||||
const relay = root.relays?.[0];
|
||||
const relay = root.relays?.[0] || relayHint;
|
||||
tags.push(
|
||||
relay ? ["e", root.id, relay, "root"] : ["e", root.id, "", "root"],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// This is the root - mark it as such
|
||||
const relay = replyTo.relay;
|
||||
tags.push(
|
||||
relay ? ["e", replyTo.id, relay, "root"] : ["e", replyTo.id, "", "root"],
|
||||
relayHint
|
||||
? ["e", replyTo.id, relayHint, "root"]
|
||||
: ["e", replyTo.id, "", "root"],
|
||||
);
|
||||
}
|
||||
|
||||
// Add reply tag (always the event we're directly replying to)
|
||||
const relay = replyTo.relay;
|
||||
tags.push(
|
||||
relay ? ["e", replyTo.id, relay, "reply"] : ["e", replyTo.id, "", "reply"],
|
||||
relayHint
|
||||
? ["e", replyTo.id, relayHint, "reply"]
|
||||
: ["e", replyTo.id, "", "reply"],
|
||||
);
|
||||
|
||||
// Collect all mentioned pubkeys
|
||||
@@ -59,16 +66,6 @@ export function buildNip10Tags(
|
||||
// Add author of reply-to event
|
||||
mentionedPubkeys.add(replyTo.pubkey);
|
||||
|
||||
// Add authors from thread history
|
||||
if (references.mentions) {
|
||||
for (const mention of references.mentions) {
|
||||
const pointer = mention.e || mention.a;
|
||||
if (pointer && "pubkey" in pointer && pointer.pubkey) {
|
||||
mentionedPubkeys.add(pointer.pubkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add additional mentions
|
||||
for (const pubkey of additionalMentions) {
|
||||
mentionedPubkeys.add(pubkey);
|
||||
@@ -81,7 +78,7 @@ export function buildNip10Tags(
|
||||
|
||||
return {
|
||||
tags,
|
||||
relayHint: relay,
|
||||
relayHint,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -104,6 +101,10 @@ export function buildNip22Tags(
|
||||
): ThreadTags {
|
||||
const tags: string[][] = [];
|
||||
|
||||
// Get relay hint from where event was seen
|
||||
const seenRelaysSet = getSeenRelays(replyTo);
|
||||
const relayHint = seenRelaysSet ? Array.from(seenRelaysSet)[0] : undefined;
|
||||
|
||||
// Add K tag (kind of parent event)
|
||||
tags.push(["K", String(replyTo.kind)]);
|
||||
|
||||
@@ -114,14 +115,12 @@ export function buildNip22Tags(
|
||||
// Use A tag for parameterized replaceable events
|
||||
const dTag = replyTo.tags.find((t: string[]) => t[0] === "d")?.[1] || "";
|
||||
const coordinate = `${replyTo.kind}:${replyTo.pubkey}:${dTag}`;
|
||||
const relay = replyTo.relay;
|
||||
tags.push(relay ? ["A", coordinate, relay] : ["A", coordinate]);
|
||||
tags.push(relayHint ? ["A", coordinate, relayHint] : ["A", coordinate]);
|
||||
} else {
|
||||
// Use E tag for regular and replaceable events
|
||||
const relay = replyTo.relay;
|
||||
tags.push(
|
||||
relay
|
||||
? ["E", replyTo.id, relay, replyTo.pubkey]
|
||||
relayHint
|
||||
? ["E", replyTo.id, relayHint, replyTo.pubkey]
|
||||
: ["E", replyTo.id, "", replyTo.pubkey],
|
||||
);
|
||||
}
|
||||
@@ -145,7 +144,7 @@ export function buildNip22Tags(
|
||||
|
||||
return {
|
||||
tags,
|
||||
relayHint: replyTo.relay,
|
||||
relayHint,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user