|
|
|
|
@ -4,9 +4,11 @@ import { getUserMetadata, NDKRelaySetFromNDK, toNpub } from "$lib/utils/nostrUti
@@ -4,9 +4,11 @@ import { getUserMetadata, NDKRelaySetFromNDK, toNpub } from "$lib/utils/nostrUti
|
|
|
|
|
import { get } from "svelte/store"; |
|
|
|
|
import { ndkInstance } from "$lib/ndk"; |
|
|
|
|
import { searchRelays } from "$lib/consts"; |
|
|
|
|
import { userStore } from "$lib/stores/userStore"; |
|
|
|
|
import { userStore, type UserState } from "$lib/stores/userStore"; |
|
|
|
|
import { buildCompleteRelaySet } from "$lib/utils/relay_management"; |
|
|
|
|
import { neventEncode } from "$lib/utils"; |
|
|
|
|
import { nip19 } from "nostr-tools"; |
|
|
|
|
import type NDK from "@nostr-dev-kit/ndk"; |
|
|
|
|
|
|
|
|
|
// AI-NOTE: Notification-specific utility functions that don't exist elsewhere
|
|
|
|
|
|
|
|
|
|
@ -82,19 +84,22 @@ export async function renderQuotedContent(message: NDKEvent, publicMessages: NDK
@@ -82,19 +84,22 @@ export async function renderQuotedContent(message: NDKEvent, publicMessages: NDK
|
|
|
|
|
const eventId = qTag[1]; |
|
|
|
|
|
|
|
|
|
if (eventId) { |
|
|
|
|
// Validate eventId format (should be 64 character hex string)
|
|
|
|
|
const isValidEventId = /^[a-fA-F0-9]{64}$/.test(eventId); |
|
|
|
|
|
|
|
|
|
// First try to find in local messages
|
|
|
|
|
let quotedMessage = publicMessages.find(msg => msg.id === eventId); |
|
|
|
|
|
|
|
|
|
// If not found locally, fetch from relays
|
|
|
|
|
if (!quotedMessage) { |
|
|
|
|
try { |
|
|
|
|
const ndk = get(ndkInstance); |
|
|
|
|
const ndk: NDK | undefined = get(ndkInstance); |
|
|
|
|
if (ndk) { |
|
|
|
|
const userStoreValue = get(userStore); |
|
|
|
|
const user = userStoreValue.signedIn && userStoreValue.pubkey ? ndk.getUser({ pubkey: userStoreValue.pubkey }) : null; |
|
|
|
|
const relaySet = await buildCompleteRelaySet(ndk, user); |
|
|
|
|
const allRelays = [...relaySet.inboxRelays, ...relaySet.outboxRelays, ...searchRelays]; |
|
|
|
|
|
|
|
|
|
const userStoreValue: UserState = get(userStore); |
|
|
|
|
const user = userStoreValue.signedIn && userStoreValue.pubkey ? ndk.getUser({ pubkey: userStoreValue.pubkey }) : null; |
|
|
|
|
const relaySet = await buildCompleteRelaySet(ndk, user); |
|
|
|
|
const allRelays = [...relaySet.inboxRelays, ...relaySet.outboxRelays, ...searchRelays]; |
|
|
|
|
|
|
|
|
|
if (allRelays.length > 0) { |
|
|
|
|
const ndkRelaySet = NDKRelaySetFromNDK.fromRelayUrls(allRelays, ndk); |
|
|
|
|
const fetchedEvent = await ndk.fetchEvent({ ids: [eventId], limit: 1 }, undefined, ndkRelaySet); |
|
|
|
|
@ -111,9 +116,20 @@ export async function renderQuotedContent(message: NDKEvent, publicMessages: NDK
@@ -111,9 +116,20 @@ export async function renderQuotedContent(message: NDKEvent, publicMessages: NDK
|
|
|
|
|
const parsedContent = await parseBasicmarkup(quotedContent); |
|
|
|
|
return `<div class="block w-fit my-2 px-3 py-2 bg-gray-200 dark:bg-gray-700 border-l-2 border-gray-400 dark:border-gray-500 rounded cursor-pointer hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-sm text-gray-600 dark:text-gray-300" onclick="window.dispatchEvent(new CustomEvent('jump-to-message', { detail: '${eventId}' }))">${parsedContent}</div>`; |
|
|
|
|
} else { |
|
|
|
|
// Fallback to nevent link
|
|
|
|
|
const nevent = neventEncode({ id: eventId } as any, []); |
|
|
|
|
return `<div class="block w-fit my-2 px-3 py-2 bg-gray-200 dark:bg-gray-700 border-l-2 border-gray-400 dark:border-gray-500 rounded cursor-pointer hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-sm text-gray-600 dark:text-gray-300" onclick="window.location.href='/events?id=${nevent}'">Quoted message not found. Click to view event ${eventId.slice(0, 8)}...</div>`; |
|
|
|
|
// Fallback to nevent link - only if eventId is valid
|
|
|
|
|
if (isValidEventId) { |
|
|
|
|
try { |
|
|
|
|
const nevent = nip19.neventEncode({ id: eventId }); |
|
|
|
|
return `<div class="block w-fit my-2 px-3 py-2 bg-gray-200 dark:bg-gray-700 border-l-2 border-gray-400 dark:border-gray-500 rounded cursor-pointer hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors text-sm text-gray-600 dark:text-gray-300" onclick="window.location.href='/events?id=${nevent}'">Quoted message not found. Click to view event ${eventId.slice(0, 8)}...</div>`; |
|
|
|
|
} catch (error) { |
|
|
|
|
console.warn(`[renderQuotedContent] Failed to encode nevent for ${eventId}:`, error); |
|
|
|
|
// Fall back to just showing the event ID without a link
|
|
|
|
|
return `<div class="block w-fit my-2 px-3 py-2 bg-gray-200 dark:bg-gray-700 border-l-2 border-gray-400 dark:border-gray-500 rounded text-sm text-gray-600 dark:text-gray-300">Quoted message not found. Event ID: ${eventId.slice(0, 8)}...</div>`; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// Invalid event ID format
|
|
|
|
|
return `<div class="block w-fit my-2 px-3 py-2 bg-gray-200 dark:bg-gray-700 border-l-2 border-gray-400 dark:border-gray-500 rounded text-sm text-gray-600 dark:text-gray-300">Invalid quoted message reference</div>`; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -161,7 +177,7 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
@@ -161,7 +177,7 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
|
|
|
|
|
// Try search relays
|
|
|
|
|
for (const relay of searchRelays) { |
|
|
|
|
try { |
|
|
|
|
const ndk = get(ndkInstance); |
|
|
|
|
const ndk: NDK | undefined = get(ndkInstance); |
|
|
|
|
if (!ndk) break; |
|
|
|
|
|
|
|
|
|
const relaySet = NDKRelaySetFromNDK.fromRelayUrls([relay], ndk); |
|
|
|
|
@ -187,10 +203,10 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
@@ -187,10 +203,10 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
|
|
|
|
|
|
|
|
|
|
// Try all available relays as fallback
|
|
|
|
|
try { |
|
|
|
|
const ndk = get(ndkInstance); |
|
|
|
|
const ndk: NDK | undefined = get(ndkInstance); |
|
|
|
|
if (!ndk) return; |
|
|
|
|
|
|
|
|
|
const userStoreValue = get(userStore); |
|
|
|
|
const userStoreValue: UserState = get(userStore); |
|
|
|
|
const user = userStoreValue.signedIn && userStoreValue.pubkey ? ndk.getUser({ pubkey: userStoreValue.pubkey }) : null; |
|
|
|
|
const relaySet = await buildCompleteRelaySet(ndk, user); |
|
|
|
|
const allRelays = [...relaySet.inboxRelays, ...relaySet.outboxRelays]; |
|
|
|
|
@ -216,10 +232,10 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
@@ -216,10 +232,10 @@ export async function fetchAuthorProfiles(events: NDKEvent[]): Promise<Map<strin
|
|
|
|
|
console.warn(`[fetchAuthorProfiles] Failed to fetch profile from all relays:`, error); |
|
|
|
|
} |
|
|
|
|
} catch (error) { |
|
|
|
|
console.warn(`[fetchAuthorProfiles] Failed to fetch profile for ${pubkey}:`, error); |
|
|
|
|
console.warn(`[fetchAuthorProfiles] Error processing profile for ${pubkey}:`, error); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
await Promise.allSettled(profilePromises); |
|
|
|
|
await Promise.all(profilePromises); |
|
|
|
|
return authorProfiles; |
|
|
|
|
} |
|
|
|
|
|