You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
5.1 KiB
171 lines
5.1 KiB
<script lang="ts"> |
|
import { userBadge } from "$lib/snippets/UserSnippets.svelte"; |
|
import CardActions from "$components/util/CardActions.svelte"; |
|
import Interactions from "$components/util/Interactions.svelte"; |
|
import { P } from "flowbite-svelte"; |
|
import { getMatchingTags } from "$lib/utils/nostrUtils"; |
|
import { goto } from "$app/navigation"; |
|
import LazyImage from "$components/util/LazyImage.svelte"; |
|
import { generateDarkPastelColor } from "$lib/utils/image_utils"; |
|
|
|
// isModal |
|
// - don't show interactions in modal view |
|
// - don't show all the details when _not_ in modal view |
|
let { event, isModal = false } = $props(); |
|
|
|
let title: string = $derived(getMatchingTags(event, "title")[0]?.[1]); |
|
let author: string = $derived( |
|
getMatchingTags(event, "author")[0]?.[1] ?? "unknown", |
|
); |
|
let version: string = $derived( |
|
getMatchingTags(event, "version")[0]?.[1] ?? "1", |
|
); |
|
let image: string = $derived(getMatchingTags(event, "image")[0]?.[1] ?? null); |
|
let summary: string = $derived( |
|
getMatchingTags(event, "summary")[0]?.[1] ?? null, |
|
); |
|
let type: string = $derived(getMatchingTags(event, "type")[0]?.[1] ?? null); |
|
let language: string = $derived(getMatchingTags(event, "l")[0]?.[1] ?? null); |
|
let source: string = $derived( |
|
getMatchingTags(event, "source")[0]?.[1] ?? null, |
|
); |
|
let publisher: string = $derived( |
|
getMatchingTags(event, "published_by")[0]?.[1] ?? null, |
|
); |
|
let identifier: string = $derived( |
|
getMatchingTags(event, "i")[0]?.[1] ?? null, |
|
); |
|
let hashtags: string[] = $derived( |
|
getMatchingTags(event, "t").map((tag) => tag[1]), |
|
); |
|
let rootId: string = $derived(getMatchingTags(event, "d")[0]?.[1] ?? null); |
|
let kind = $derived(event.kind); |
|
|
|
let authorTag: string = $derived( |
|
getMatchingTags(event, "author")[0]?.[1] ?? "", |
|
); |
|
let pTag: string = $derived(getMatchingTags(event, "p")[0]?.[1] ?? ""); |
|
let originalAuthor: string = $derived( |
|
getMatchingTags(event, "p")[0]?.[1] ?? null, |
|
); |
|
|
|
function isValidNostrPubkey(str: string): boolean { |
|
return ( |
|
/^[a-f0-9]{64}$/i.test(str) || |
|
(str.startsWith("npub1") && str.length >= 59 && str.length <= 63) |
|
); |
|
} |
|
</script> |
|
|
|
<div class="flex flex-col relative mb-2"> |
|
{#if !isModal} |
|
<div class="flex flex-row justify-between items-center"> |
|
<!-- Index author badge --> |
|
<P class="text-base font-normal" |
|
>{@render userBadge(event.pubkey, author)}</P |
|
> |
|
<CardActions {event}></CardActions> |
|
</div> |
|
{/if} |
|
<div |
|
class="flex-grow grid grid-cols-1 md:grid-cols-[auto_1fr] gap-4 items-center" |
|
> |
|
<div class="my-2"> |
|
{#if image} |
|
<LazyImage |
|
src={image} |
|
alt={title} |
|
eventId={event.id} |
|
className="w-full md:max-w-48 object-contain rounded" |
|
/> |
|
{:else} |
|
<div |
|
class="w-full md:max-w-48 h-32 object-contain rounded" |
|
style="background-color: {generateDarkPastelColor(event.id)};" |
|
> |
|
</div> |
|
{/if} |
|
</div> |
|
<div class="space-y-4 my-4"> |
|
<h1 class="text-3xl font-bold">{title}</h1> |
|
<h2 class="text-base font-bold"> |
|
by |
|
{#if authorTag && pTag && isValidNostrPubkey(pTag)} |
|
{authorTag} {@render userBadge(pTag, "")} |
|
{:else if authorTag} |
|
{authorTag} |
|
{:else if pTag && isValidNostrPubkey(pTag)} |
|
{@render userBadge(pTag, "")} |
|
{:else if originalAuthor !== null} |
|
{@render userBadge(originalAuthor, author)} |
|
{:else} |
|
unknown |
|
{/if} |
|
</h2> |
|
{#if version !== "1"} |
|
<h4 |
|
class="text-base font-medium text-primary-700 dark:text-primary-300" |
|
> |
|
Version: {version} |
|
</h4> |
|
{/if} |
|
</div> |
|
</div> |
|
</div> |
|
|
|
{#if summary} |
|
<div class="flex flex-row my-2"> |
|
<p class="text-base text-primary-900 dark:text-highlight">{summary}</p> |
|
</div> |
|
{/if} |
|
|
|
{#if hashtags.length} |
|
<div class="tags my-2"> |
|
{#each hashtags as tag} |
|
<button |
|
onclick={() => goto(`/events?t=${encodeURIComponent(tag)}`)} |
|
class="text-sm hover:text-primary-700 dark:hover:text-primary-300 cursor-pointer" |
|
>#{tag}</button |
|
> |
|
{/each} |
|
</div> |
|
{/if} |
|
|
|
{#if isModal} |
|
<div class="flex flex-row my-4"> |
|
<h4 class="text-base font-normal mt-2"> |
|
{#if kind === 30040} |
|
<span>Index author:</span> |
|
{:else} |
|
<span>Author:</span> |
|
{/if} |
|
{@render userBadge(event.pubkey, "")} |
|
</h4> |
|
</div> |
|
|
|
<div class="flex flex-col pb-4 space-y-1"> |
|
{#if source !== null} |
|
<h5 class="text-sm"> |
|
Source: <a class="underline break-all" href={source} target="_blank" |
|
>{source}</a |
|
> |
|
</h5> |
|
{/if} |
|
{#if type !== null} |
|
<h5 class="text-sm">Publication type: {type}</h5> |
|
{/if} |
|
{#if language !== null} |
|
<h5 class="text-sm">Language: {language}</h5> |
|
{/if} |
|
{#if publisher !== null} |
|
<h5 class="text-sm">Published by: {publisher}</h5> |
|
{/if} |
|
{#if identifier !== null} |
|
<h5 class="text-sm">{identifier}</h5> |
|
{/if} |
|
</div> |
|
{/if} |
|
|
|
{#if !isModal} |
|
<Interactions {event} {rootId} direction="row" /> |
|
{/if}
|
|
|