diff --git a/src/lib/components/EventDetails.svelte b/src/lib/components/EventDetails.svelte index ca9103a..61d649a 100644 --- a/src/lib/components/EventDetails.svelte +++ b/src/lib/components/EventDetails.svelte @@ -15,6 +15,10 @@ import ContainingIndexes from "$lib/components/util/ContainingIndexes.svelte"; import Notifications from "$lib/components/Notifications.svelte"; import { parseBasicmarkup } from "$lib/utils/markup/basicMarkupParser"; +import { repostContent, quotedContent } from "$lib/components/embedded_events/EmbeddedSnippets.svelte"; +import { repostKinds } from "$lib/consts"; +import { getNdkContext } from "$lib/ndk"; +import { processNostrIdentifiers } from "$lib/utils/nostrUtils"; import type { UserProfile } from "$lib/models/user_profile"; @@ -30,6 +34,7 @@ import type { UserProfile } from "$lib/models/user_profile"; let showFullContent = $state(false); let shouldTruncate = $derived(event.content.length > 250 && !showFullContent); let parsedContent = $state(""); + let isRepost = $derived(repostKinds.includes(event.kind) || (event.kind === 1 && event.getMatchingTags("q").length > 0)); function getEventTitle(event: NDKEvent): string { // First try to get title from title tag @@ -246,12 +251,20 @@ import type { UserProfile } from "$lib/models/user_profile"; $effect(() => { if (event.content) { - parseBasicmarkup(event.content).then((parsed) => { - parsedContent = parsed; - }).catch((error) => { - console.error("Error parsing content:", error); + // For kind 6 and 16 reposts, we don't need to parse the content as basic markup since it's JSON + // For quote reposts (kind 1 with q tags), we still need to parse the content for nostr identifiers + if (repostKinds.includes(event.kind)) { parsedContent = event.content; - }); + } else { + // For all other events (including quote reposts), parse the content for nostr identifiers + // Use the proper processNostrIdentifiers function to get display names + processNostrIdentifiers(event.content, getNdkContext()).then((processed) => { + parsedContent = processed; + }).catch((error) => { + console.error("Error parsing content:", error); + parsedContent = event.content; + }); + } } else { parsedContent = ""; } @@ -324,14 +337,44 @@ import type { UserProfile } from "$lib/models/user_profile";
Content:
-
- {@html parsedContent} -
- {#if shouldTruncate} - + {#if isRepost} + + {#if repostKinds.includes(event.kind)} + +
+
+ {event.kind === 6 ? 'Reposted content:' : 'Generic reposted content:'} +
+ {@render repostContent(event.content)} +
+ {:else if event.kind === 1 && event.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(event, [], getNdkContext())} + {#if event.content && event.content.trim()} +
+
+ Added comment: +
+ {@html parsedContent} +
+ {/if} +
+ {/if} + {:else} + +
+ {@html parsedContent} +
+ {#if shouldTruncate} + + {/if} {/if}
diff --git a/src/lib/components/Notifications.svelte b/src/lib/components/Notifications.svelte index 7d1703d..e18b971 100644 --- a/src/lib/components/Notifications.svelte +++ b/src/lib/components/Notifications.svelte @@ -22,6 +22,8 @@ import { formatDate, neventEncode } from "$lib/utils"; import { NDKRelaySetFromNDK } from "$lib/utils/nostrUtils"; import { parseBasicmarkup } from "$lib/utils/markup/basicMarkupParser"; + import { repostContent } from "$lib/components/embedded_events/EmbeddedSnippets.svelte"; + import { repostKinds } from "$lib/consts"; import { getNdkContext } from "$lib/ndk"; @@ -819,9 +821,38 @@
- {#await parseBasicmarkup(message.content || "No content") then parsed} - {@html parsed} - {/await} + {#if repostKinds.includes(message.kind)} + +
+
+ {message.kind === 6 ? 'Repost:' : 'Generic repost:'} +
+ {@render repostContent(message.content)} +
+ {:else if message.kind === 1 && message.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(message, publicMessages, ndk)} + {#if message.content && message.content.trim()} +
+
+ Comment: +
+ {#await parseBasicmarkup(message.content.slice(0, 100) + (message.content.length > 100 ? "..." : "")) then parsed} + {@html parsed} + {/await} +
+ {/if} +
+ {:else} + + {#await parseBasicmarkup(message.content || "No content") then parsed} + {@html parsed} + {/await} + {/if}
@@ -900,9 +931,38 @@
- {#await parseBasicmarkup(notification.content || "No content") then parsed} - {@html parsed} - {/await} + {#if repostKinds.includes(notification.kind)} + +
+
+ {notification.kind === 6 ? 'Repost:' : 'Generic repost:'} +
+ {@render repostContent(notification.content)} +
+ {:else if notification.kind === 1 && notification.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(notification, notifications, ndk)} + {#if notification.content && notification.content.trim()} +
+
+ Comment: +
+ {#await parseBasicmarkup(notification.content.slice(0, 100) + (notification.content.length > 100 ? "..." : "")) then parsed} + {@html parsed} + {/await} +
+ {/if} +
+ {:else} + + {#await parseBasicmarkup(notification.content || "No content") then parsed} + {@html parsed} + {/await} + {/if}
diff --git a/src/lib/components/embedded_events/EmbeddedEvent.svelte b/src/lib/components/embedded_events/EmbeddedEvent.svelte index 30ef2dd..005dea8 100644 --- a/src/lib/components/embedded_events/EmbeddedEvent.svelte +++ b/src/lib/components/embedded_events/EmbeddedEvent.svelte @@ -2,7 +2,7 @@ import type { NDKEvent } from "@nostr-dev-kit/ndk"; import { fetchEventWithFallback, getUserMetadata, toNpub } from "$lib/utils/nostrUtils"; import { userBadge } from "$lib/snippets/UserSnippets.svelte"; - import { parsedContent } from "$lib/components/embedded_events/EmbeddedSnippets.svelte"; + import { parsedContent, repostContent, quotedContent } from "$lib/components/embedded_events/EmbeddedSnippets.svelte"; import { naddrEncode } from "$lib/utils"; import { activeInboxRelays, getNdkContext } from "$lib/ndk"; import { goto } from "$app/navigation"; @@ -292,14 +292,27 @@ {#if event.kind === 1 || repostKinds.includes(event.kind)}
{#if repostKinds.includes(event.kind)} - +
- Reposted content: + {event.kind === 6 ? 'Reposted content:' : 'Generic reposted content:'}
- {@render parsedContent(event.content.slice(0, 300))} - {#if event.content.length > 300} - ... + {@render repostContent(event.content)} +
+ {:else if event.kind === 1 && event.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(event, [], ndk)} + {#if event.content && event.content.trim()} +
+
+ Added comment: +
+ {@render parsedContent(event.content)} +
{/if}
{:else} diff --git a/src/lib/utils/mime.ts b/src/lib/utils/mime.ts index a8714c3..3b8e416 100644 --- a/src/lib/utils/mime.ts +++ b/src/lib/utils/mime.ts @@ -62,6 +62,18 @@ export function getMimeTags(kind: number): [string, string][] { MTag = ["M", `note/microblog/${replaceability}`]; break; + // Repost (NIP-18) + case 6: + mTag = ["m", "application/json"]; + MTag = ["M", `note/repost/${replaceability}`]; + break; + + // Generic repost (NIP-18) + case 16: + mTag = ["m", "application/json"]; + MTag = ["M", `note/generic-repost/${replaceability}`]; + break; + // Generic reply case 1111: mTag = ["m", "text/plain"]; diff --git a/src/lib/utils/nostrUtils.ts b/src/lib/utils/nostrUtils.ts index ef3e8ca..31138c7 100644 --- a/src/lib/utils/nostrUtils.ts +++ b/src/lib/utils/nostrUtils.ts @@ -179,7 +179,7 @@ export async function createProfileLinkWithVerification( /** * Create a note link element */ -function createNoteLink(identifier: string): string { +export function createNoteLink(identifier: string): string { const cleanId = identifier.replace(/^nostr:/, ""); const shortId = `${cleanId.slice(0, 12)}...${cleanId.slice(-8)}`; const escapedId = escapeHtml(cleanId); diff --git a/src/routes/events/+page.svelte b/src/routes/events/+page.svelte index 287764f..e65e02c 100644 --- a/src/routes/events/+page.svelte +++ b/src/routes/events/+page.svelte @@ -22,6 +22,8 @@ import ViewPublicationLink from "$lib/components/util/ViewPublicationLink.svelte"; import { checkCommunity } from "$lib/utils/search_utility"; import { parseBasicmarkup } from "$lib/utils/markup/basicMarkupParser"; + import { repostContent, quotedContent } from "$lib/components/embedded_events/EmbeddedSnippets.svelte"; + import { repostKinds } from "$lib/consts"; import { userStore } from "$lib/stores/userStore"; import { @@ -752,9 +754,38 @@
- {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} - {@html parsed} - {/await} + {#if repostKinds.includes(result.kind)} + +
+
+ {result.kind === 6 ? 'Repost:' : 'Generic repost:'} +
+ {@render repostContent(result.content)} +
+ {:else if result.kind === 1 && result.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(result, [], ndk)} + {#if result.content && result.content.trim()} +
+
+ Comment: +
+ {#await parseBasicmarkup(result.content.slice(0, 100) + (result.content.length > 100 ? "..." : "")) then parsed} + {@html parsed} + {/await} +
+ {/if} +
+ {:else} + + {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} + {@html parsed} + {/await} + {/if}
{/if} {/if} @@ -938,9 +969,38 @@
- {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} - {@html parsed} - {/await} + {#if repostKinds.includes(result.kind)} + +
+
+ {result.kind === 6 ? 'Repost:' : 'Generic repost:'} +
+ {@render repostContent(result.content)} +
+ {:else if result.kind === 1 && result.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(result, [], ndk)} + {#if result.content && result.content.trim()} +
+
+ Comment: +
+ {#await parseBasicmarkup(result.content.slice(0, 100) + (result.content.length > 100 ? "..." : "")) then parsed} + {@html parsed} + {/await} +
+ {/if} +
+ {:else} + + {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} + {@html parsed} + {/await} + {/if}
{/if} {/if} @@ -1110,9 +1170,38 @@
- {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} - {@html parsed} - {/await} + {#if repostKinds.includes(result.kind)} + +
+
+ {result.kind === 6 ? 'Repost:' : 'Generic repost:'} +
+ {@render repostContent(result.content)} +
+ {:else if result.kind === 1 && result.getMatchingTags("q").length > 0} + +
+
+ Quote repost: +
+ {@render quotedContent(result, [], ndk)} + {#if result.content && result.content.trim()} +
+
+ Comment: +
+ {#await parseBasicmarkup(result.content.slice(0, 100) + (result.content.length > 100 ? "..." : "")) then parsed} + {@html parsed} + {/await} +
+ {/if} +
+ {:else} + + {#await parseBasicmarkup(result.content.slice(0, 200) + (result.content.length > 200 ? "..." : "")) then parsed} + {@html parsed} + {/await} + {/if}
{/if} {/if}