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
6.1 KiB
171 lines
6.1 KiB
<script lang="ts"> |
|
import { Heading, P } from "flowbite-svelte"; |
|
import { onMount } from "svelte"; |
|
import { page } from "$app/stores"; |
|
import type { NDKEvent } from '$lib/utils/nostrUtils'; |
|
import EventSearch from '$lib/components/EventSearch.svelte'; |
|
import EventDetails from '$lib/components/EventDetails.svelte'; |
|
import RelayActions from '$lib/components/RelayActions.svelte'; |
|
import CommentBox from '$lib/components/CommentBox.svelte'; |
|
import { userBadge } from '$lib/snippets/UserSnippets.svelte'; |
|
import { getMatchingTags, toNpub } from '$lib/utils/nostrUtils'; |
|
|
|
let loading = $state(false); |
|
let error = $state<string | null>(null); |
|
let searchValue = $state<string | null>(null); |
|
let dTagValue = $state<string | null>(null); |
|
let event = $state<NDKEvent | null>(null); |
|
let searchResults = $state<NDKEvent[]>([]); |
|
let profile = $state<{ |
|
name?: string; |
|
display_name?: string; |
|
about?: string; |
|
picture?: string; |
|
banner?: string; |
|
website?: string; |
|
lud16?: string; |
|
nip05?: string; |
|
} | null>(null); |
|
let userPubkey = $state<string | null>(null); |
|
let userRelayPreference = $state(false); |
|
|
|
function handleEventFound(newEvent: NDKEvent) { |
|
event = newEvent; |
|
searchResults = []; |
|
if (newEvent.kind === 0) { |
|
try { |
|
profile = JSON.parse(newEvent.content); |
|
} catch { |
|
profile = null; |
|
} |
|
} else { |
|
profile = null; |
|
} |
|
} |
|
|
|
function handleSearchResults(results: NDKEvent[]) { |
|
searchResults = results; |
|
event = null; |
|
profile = null; |
|
} |
|
|
|
function getSummary(event: NDKEvent): string | undefined { |
|
return getMatchingTags(event, 'summary')[0]?.[1]; |
|
} |
|
|
|
function getDeferrelNaddr(event: NDKEvent): string | undefined { |
|
// Look for a 'deferrel' tag, e.g. ['deferrel', 'naddr1...'] |
|
return getMatchingTags(event, 'deferrel')[0]?.[1]; |
|
} |
|
|
|
$effect(() => { |
|
const id = $page.url.searchParams.get('id'); |
|
const dTag = $page.url.searchParams.get('d'); |
|
|
|
if (id !== searchValue) { |
|
searchValue = id; |
|
dTagValue = null; |
|
} |
|
|
|
if (dTag !== dTagValue) { |
|
dTagValue = dTag; |
|
searchValue = null; |
|
} |
|
}); |
|
|
|
onMount(async () => { |
|
// Get user's pubkey and relay preference from localStorage |
|
userPubkey = localStorage.getItem('userPubkey'); |
|
userRelayPreference = localStorage.getItem('useUserRelays') === 'true'; |
|
}); |
|
</script> |
|
|
|
<div class="w-full flex justify-center"> |
|
<main class="main-leather flex flex-col space-y-6 max-w-2xl w-full my-6 px-4"> |
|
<div class="flex justify-between items-center"> |
|
<Heading tag="h1" class="h-leather mb-2">Events</Heading> |
|
</div> |
|
|
|
<P class="mb-3"> |
|
Use this page to view any event (npub, nprofile, nevent, naddr, note, pubkey, or eventID). |
|
You can also search for events by d-tag using the format "d:tag-name". |
|
</P> |
|
|
|
<EventSearch |
|
{loading} |
|
{error} |
|
{searchValue} |
|
{dTagValue} |
|
{event} |
|
onEventFound={handleEventFound} |
|
onSearchResults={handleSearchResults} |
|
/> |
|
|
|
{#if event} |
|
<EventDetails {event} {profile} {searchValue} /> |
|
<RelayActions {event} /> |
|
{#if userPubkey} |
|
<div class="mt-8"> |
|
<Heading tag="h2" class="h-leather mb-4">Add Comment</Heading> |
|
<CommentBox event={event} userPubkey={userPubkey} userRelayPreference={userRelayPreference} /> |
|
</div> |
|
{:else} |
|
<div class="mt-8 p-4 bg-gray-200 dark:bg-gray-700 rounded-lg"> |
|
<P>Please sign in to add comments.</P> |
|
</div> |
|
{/if} |
|
{/if} |
|
|
|
{#if searchResults.length > 0} |
|
<div class="mt-8"> |
|
<Heading tag="h2" class="h-leather mb-4"> |
|
Search Results for d-tag: "{dTagValue}" ({searchResults.length} events) |
|
</Heading> |
|
<div class="space-y-4"> |
|
{#each searchResults as result, index} |
|
<button |
|
class="w-full text-left border border-gray-300 dark:border-gray-600 rounded-lg p-4 bg-white dark:bg-primary-900/70 hover:bg-gray-100 dark:hover:bg-primary-800 focus:bg-gray-100 dark:focus:bg-primary-800 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors overflow-hidden" |
|
onclick={() => handleEventFound(result)} |
|
> |
|
<div class="flex flex-col gap-1"> |
|
<div class="flex items-center gap-2 mb-1"> |
|
<span class="font-medium text-gray-800 dark:text-gray-100">Event {index + 1}</span> |
|
<span class="text-xs text-gray-600 dark:text-gray-400">Kind: {result.kind}</span> |
|
<span class="text-xs text-gray-600 dark:text-gray-400"> |
|
{@render userBadge(toNpub(result.pubkey) as string, undefined)} |
|
</span> |
|
<span class="text-xs text-gray-500 dark:text-gray-400 ml-auto"> |
|
{result.created_at ? new Date(result.created_at * 1000).toLocaleDateString() : 'Unknown date'} |
|
</span> |
|
</div> |
|
{#if getSummary(result)} |
|
<div class="text-sm text-primary-900 dark:text-primary-200 mb-1 line-clamp-2"> |
|
{getSummary(result)} |
|
</div> |
|
{/if} |
|
{#if getDeferrelNaddr(result)} |
|
<div class="text-xs text-primary-800 dark:text-primary-300 mb-1"> |
|
Read |
|
<a |
|
class="underline text-primary-700 dark:text-primary-400 hover:text-primary-900 dark:hover:text-primary-200 break-all" |
|
href={'/publications?d=' + encodeURIComponent(dTagValue || '')} |
|
onclick={e => e.stopPropagation()} |
|
tabindex="0" |
|
> |
|
{getDeferrelNaddr(result)} |
|
</a> |
|
</div> |
|
{/if} |
|
{#if result.content} |
|
<div class="text-sm text-gray-800 dark:text-gray-200 mt-1 line-clamp-2 break-words"> |
|
{result.content.slice(0, 200)}{result.content.length > 200 ? '...' : ''} |
|
</div> |
|
{/if} |
|
</div> |
|
</button> |
|
{/each} |
|
</div> |
|
</div> |
|
{/if} |
|
</main> |
|
</div>
|
|
|