Browse Source

render embedded reposts

master
silberengel 7 months ago
parent
commit
f2e3cc08b2
  1. 17
      src/lib/components/Notifications.svelte
  2. 42
      src/lib/utils/notification_utils.ts

17
src/lib/components/Notifications.svelte

@ -22,6 +22,7 @@
truncateContent, truncateContent,
truncateRenderedContent, truncateRenderedContent,
parseContent, parseContent,
parseRepostContent,
renderQuotedContent, renderQuotedContent,
getNotificationType, getNotificationType,
fetchAuthorProfiles fetchAuthorProfiles
@ -692,7 +693,7 @@
</script> </script>
{#if isOwnProfile && $userStore.signedIn} {#if isOwnProfile && $userStore.signedIn}
<div class="mb-6"> <div class="mb-6 w-full overflow-x-hidden">
<div class="flex items-center justify-between mb-4"> <div class="flex items-center justify-between mb-4">
<Heading tag="h3" class="h-leather">Notifications</Heading> <Heading tag="h3" class="h-leather">Notifications</Heading>
@ -740,7 +741,7 @@
<P>No public messages found.</P> <P>No public messages found.</P>
</div> </div>
{:else} {:else}
<div class="max-h-[72rem] overflow-y-auto"> <div class="max-h-[72rem] overflow-y-auto overflow-x-hidden">
{#if filteredByUser} {#if filteredByUser}
<div class="filter-indicator mb-4 p-3 rounded-lg"> <div class="filter-indicator mb-4 p-3 rounded-lg">
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
@ -818,7 +819,7 @@
</div> </div>
<!-- Message Content --> <!-- Message Content -->
<div class="message-content flex-1 {isFromUser ? 'text-right' : ''}"> <div class="message-content flex-1 min-w-0 {isFromUser ? 'text-right' : ''}">
<div class="flex items-center gap-2 mb-2 {isFromUser ? 'justify-end' : ''}"> <div class="flex items-center gap-2 mb-2 {isFromUser ? 'justify-end' : ''}">
<span class="text-xs font-medium text-primary-600 dark:text-primary-400 bg-primary-100 dark:bg-primary-900 px-2 py-1 rounded"> <span class="text-xs font-medium text-primary-600 dark:text-primary-400 bg-primary-100 dark:bg-primary-900 px-2 py-1 rounded">
{isFromUser ? 'Your Message' : 'Public Message'} {isFromUser ? 'Your Message' : 'Public Message'}
@ -848,12 +849,14 @@
{/if} {/if}
{#if message.content} {#if message.content}
<div class="text-sm text-gray-800 dark:text-gray-200 mb-2 leading-relaxed"> <div class="text-sm text-gray-800 dark:text-gray-200 mb-2 leading-relaxed">
{#await parseContent(message.content) then parsedContent} <div class="px-2">
{#await ((message.kind === 6 || message.kind === 16) ? parseRepostContent(message.content) : parseContent(message.content)) then parsedContent}
{@html parsedContent} {@html parsedContent}
{:catch} {:catch}
{@html message.content} {@html message.content}
{/await} {/await}
</div> </div>
</div>
{/if} {/if}
@ -877,7 +880,7 @@
<P>No notifications {notificationMode === "to-me" ? "received" : "sent"} found.</P> <P>No notifications {notificationMode === "to-me" ? "received" : "sent"} found.</P>
</div> </div>
{:else} {:else}
<div class="max-h-[72rem] overflow-y-auto space-y-4"> <div class="max-h-[72rem] overflow-y-auto overflow-x-hidden space-y-4">
{#each notifications.slice(0, 100) as notification} {#each notifications.slice(0, 100) as notification}
{@const authorProfile = authorProfiles.get(notification.pubkey)} {@const authorProfile = authorProfiles.get(notification.pubkey)}
<div class="message-container p-4 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm"> <div class="message-container p-4 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
@ -929,12 +932,14 @@
{#if notification.content} {#if notification.content}
<div class="text-sm text-gray-800 dark:text-gray-200 mb-2 leading-relaxed"> <div class="text-sm text-gray-800 dark:text-gray-200 mb-2 leading-relaxed">
{#await parseContent(notification.content) then parsedContent} <div class="px-2">
{#await ((notification.kind === 6 || notification.kind === 16) ? parseRepostContent(notification.content) : parseContent(notification.content)) then parsedContent}
{@html parsedContent} {@html parsedContent}
{:catch} {:catch}
{@html truncateContent(notification.content)} {@html truncateContent(notification.content)}
{/await} {/await}
</div> </div>
</div>
{/if} {/if}

42
src/lib/utils/notification_utils.ts

@ -73,6 +73,48 @@ export async function parseContent(content: string): Promise<string> {
return await parseBasicmarkup(content); return await parseBasicmarkup(content);
} }
/**
* Parses repost content and renders it as an embedded event
*/
export async function parseRepostContent(content: string): Promise<string> {
if (!content) return "";
try {
// Try to parse the content as JSON (repost events contain the original event as JSON)
const originalEvent = JSON.parse(content);
// Extract the original event's content
const originalContent = originalEvent.content || "";
const originalAuthor = originalEvent.pubkey || "";
const originalCreatedAt = originalEvent.created_at || 0;
// Parse the original content with basic markup
const parsedOriginalContent = await parseBasicmarkup(originalContent);
// Create an embedded event display
const formattedDate = originalCreatedAt ? new Date(originalCreatedAt * 1000).toLocaleDateString() : "Unknown date";
const shortAuthor = originalAuthor ? `${originalAuthor.slice(0, 8)}...${originalAuthor.slice(-4)}` : "Unknown";
return `
<div class="embedded-repost bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-3 my-2">
<div class="flex items-center gap-2 mb-2 text-xs text-gray-600 dark:text-gray-400">
<span class="font-medium">Reposted by:</span>
<span class="font-mono">${shortAuthor}</span>
<span></span>
<span>${formattedDate}</span>
</div>
<div class="text-sm text-gray-800 dark:text-gray-200 leading-relaxed">
${parsedOriginalContent}
</div>
</div>
`;
} catch (error) {
// If JSON parsing fails, fall back to basic markup
console.warn("Failed to parse repost content as JSON, falling back to basic markup:", error);
return await parseBasicmarkup(content);
}
}
/** /**
* Renders quoted content for a message * Renders quoted content for a message
*/ */

Loading…
Cancel
Save