mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-12 08:27:27 +02:00
fix: Fix e-tag reply resolution for NIP-17 rumor IDs
The e-tags in NIP-17 messages reference the innermost event (rumor) IDs, not the gift wrap IDs. Updated ReplyPreview to properly handle this: - Add local state fallback for when eventStore doesn't track synthetic events - Use adapter's loadReplyMessage() return value directly - syntheticEventCache now reliably provides rumor events for reply previews This ensures reply previews work correctly even if eventStore doesn't properly index events with empty signatures.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { memo, useEffect } from "react";
|
||||
import { memo, useEffect, useState } from "react";
|
||||
import { use$ } from "applesauce-react/hooks";
|
||||
import eventStore from "@/services/event-store";
|
||||
import { UserName } from "../nostr/UserName";
|
||||
import { RichText } from "../nostr/RichText";
|
||||
import type { ChatProtocolAdapter } from "@/lib/chat/adapters/base-adapter";
|
||||
import type { Conversation } from "@/types/chat";
|
||||
import type { NostrEvent } from "@/types/nostr";
|
||||
|
||||
interface ReplyPreviewProps {
|
||||
replyToId: string;
|
||||
@@ -16,6 +17,10 @@ interface ReplyPreviewProps {
|
||||
/**
|
||||
* ReplyPreview - Shows who is being replied to with truncated message content
|
||||
* Automatically fetches missing events from protocol-specific relays
|
||||
*
|
||||
* For NIP-17 (gift-wrapped DMs), reply targets reference rumor IDs (innermost events).
|
||||
* These are stored as synthetic events in adapter caches since eventStore may not
|
||||
* properly index events with empty signatures.
|
||||
*/
|
||||
export const ReplyPreview = memo(function ReplyPreview({
|
||||
replyToId,
|
||||
@@ -23,18 +28,33 @@ export const ReplyPreview = memo(function ReplyPreview({
|
||||
conversation,
|
||||
onScrollToMessage,
|
||||
}: ReplyPreviewProps) {
|
||||
// Load the event being replied to (reactive - updates when event arrives)
|
||||
const replyEvent = use$(() => eventStore.event(replyToId), [replyToId]);
|
||||
// State for manually loaded events (NIP-17 synthetic events)
|
||||
const [manualEvent, setManualEvent] = useState<NostrEvent | null>(null);
|
||||
|
||||
// Fetch event from relays if not in store
|
||||
// Load the event being replied to (reactive - updates when event arrives)
|
||||
const storeEvent = use$(() => eventStore.event(replyToId), [replyToId]);
|
||||
|
||||
// Use store event if available, otherwise fall back to manually loaded event
|
||||
const replyEvent = storeEvent ?? manualEvent;
|
||||
|
||||
// Fetch event from adapter if not in store
|
||||
useEffect(() => {
|
||||
if (!replyEvent) {
|
||||
adapter.loadReplyMessage(conversation, replyToId).catch((err) => {
|
||||
console.error(
|
||||
`[ReplyPreview] Failed to load reply ${replyToId.slice(0, 8)}:`,
|
||||
err,
|
||||
);
|
||||
});
|
||||
adapter
|
||||
.loadReplyMessage(conversation, replyToId)
|
||||
.then((event) => {
|
||||
if (event) {
|
||||
// For NIP-17, eventStore may not track synthetic events properly
|
||||
// Store it in local state to ensure it displays
|
||||
setManualEvent(event);
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(
|
||||
`[ReplyPreview] Failed to load reply ${replyToId.slice(0, 8)}:`,
|
||||
err,
|
||||
);
|
||||
});
|
||||
}
|
||||
}, [replyEvent, adapter, conversation, replyToId]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user