diff --git a/src/components/ComposeDialog.tsx b/src/components/ComposeDialog.tsx index c858292..7efbb43 100644 --- a/src/components/ComposeDialog.tsx +++ b/src/components/ComposeDialog.tsx @@ -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); diff --git a/src/components/RelaySelector.tsx b/src/components/RelaySelector.tsx index 6a0387e..bea101d 100644 --- a/src/components/RelaySelector.tsx +++ b/src/components/RelaySelector.tsx @@ -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 ( @@ -125,54 +103,33 @@ export function RelaySelector({ {/* Selected Relays */} - {selectedRelays.length > 0 && ( -
-
- SELECTED ({selectedRelays.length}) -
+ + {selectedRelays.length > 0 ? (
{selectedRelays.map((relay: string) => ( - { - handleRemoveRelay(relay); - }} - /> + className="flex items-center gap-2 p-2 rounded-md bg-muted/50" + > +
+
{relay}
+
+ +
))}
- - )} - - {/* Available Relays */} - -
-
- AVAILABLE + ) : ( +
+ No relays selected. Add relays below.
- {knownRelays - .filter((relay: string) => !selectedRelays.includes(relay)) - .map((relay: string) => ( - { - handleToggleRelay(relay); - }} - /> - ))} - - {knownRelays.filter((r: string) => !selectedRelays.includes(r)) - .length === 0 && ( -
- No other relays available -
- )} -
+ )} {/* Add Relay */} @@ -205,60 +162,3 @@ export function RelaySelector({ ); } - -/** - * Individual relay item - */ -function RelayItem({ - relay, - status, - selected, - onToggle, -}: { - relay: string; - status: "connected" | "connecting" | "disconnected"; - selected: boolean; - onToggle: () => void; -}) { - return ( -
- {/* Status Indicator */} - {status === "connected" && ( - - )} - {status === "connecting" && ( - - )} - {status === "disconnected" && ( - - )} - - {/* Relay URL */} -
-
{relay}
-
- - {/* Selection Indicator */} - {selected ? ( - - ) : ( - - )} -
- ); -} diff --git a/src/lib/thread-builder.ts b/src/lib/thread-builder.ts index 1b46e87..394f951 100644 --- a/src/lib/thread-builder.ts +++ b/src/lib/thread-builder.ts @@ -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, }; }