Browse Source

feat: event previews for issues, patches and repos

to be displayed when they are embedded into events
master
DanConwayDev 2 years ago
parent
commit
ea07b55491
No known key found for this signature in database
GPG Key ID: 68E15486D73F75E1
  1. 2
      src/lib/components/events/EventWrapperLite.svelte
  2. 21
      src/lib/components/events/content/IssuePreview.svelte
  3. 2
      src/lib/components/events/content/ParsedContent.svelte
  4. 335
      src/lib/components/events/content/Patch.svelte
  5. 19
      src/lib/components/events/content/Repo.svelte
  6. 41
      src/lib/components/events/content/utils.ts
  7. 24
      src/lib/wrappers/EventCard.svelte
  8. 102
      src/lib/wrappers/EventPreview.svelte

2
src/lib/components/events/EventWrapperLite.svelte

@ -18,6 +18,6 @@ @@ -18,6 +18,6 @@
<UserHeader user={author} inline />
</div>
</div>
<span class="m-auto pr-1 text-xs">{created_at_ago}</span>
<span class="m-auto flex-none py-1 text-xs">{created_at_ago}</span>
</div>
</div>

21
src/lib/components/events/content/IssuePreview.svelte

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
<script lang="ts">
import { extractAReference } from '$lib/components/repo/utils'
import { extractRepoAFromProposalEvent } from '$lib/stores/Proposals'
import type { NDKEvent } from '@nostr-dev-kit/ndk'
import { nip19 } from 'nostr-tools'
export let event: NDKEvent
let nevent = nip19.neventEncode({
id: event.id,
relays: event.relay ? [event.relay.url] : undefined,
})
let a_string = extractRepoAFromProposalEvent(event)
let pointer = a_string ? extractAReference(a_string) : undefined
let naddr = pointer ? nip19.naddrEncode(pointer) : undefined
</script>
<span>
Git Issue for <a class="opacity-50" href={`/e/${naddr}`}
>{pointer?.identifier}</a
>: <a href={`/e/${nevent}`}>{event.content?.split('\n')[0]}</a> by
</span>

2
src/lib/components/events/content/ParsedContent.svelte

@ -43,7 +43,7 @@ @@ -43,7 +43,7 @@
<UserHeader user={part.hex} inline={true} size="sm" />
</div>
{:else if isParsedNevent(part) || isParsedNote(part) || isParsedNaddr(part)}
<EventPreview parsed_nostr_ref={part} />
<EventPreview pointer={part.data} />
{:else if isParsedText(part)}
{part.value}
{/if}

335
src/lib/components/events/content/Patch.svelte

@ -1,20 +1,28 @@ @@ -1,20 +1,28 @@
<script lang="ts">
import type { NDKTag } from '@nostr-dev-kit/ndk'
import type { NDKEvent, NDKTag } from '@nostr-dev-kit/ndk'
import parseDiff from 'parse-diff'
import hljs from 'highlight.js/lib/common'
import 'highlight.js/styles/agate.min.css'
import type { Change, AddChange, DeleteChange } from 'parse-diff'
import ParsedContent from './ParsedContent.svelte'
import { extractPatchMessage } from './utils'
import { extractPatchMessage, extractTagContent } from './utils'
import { nip19 } from 'nostr-tools'
import { extractRepoAFromProposalEvent } from '$lib/stores/Proposals'
import { extractAReference } from '$lib/components/repo/utils'
export let event: NDKEvent
export let preview = false
let content: string = event ? event.content : ''
let tags: NDKTag[] = event ? event.tags : []
export let content: string = ''
export let tags: NDKTag[] = []
let commit_id_shorthand =
extractTagContent('commit')?.substring(0, 8) || '[commit_id unknown]'
extractTagContent('commit', tags)?.substring(0, 8) || '[commit_id unknown]'
let commit_message =
extractTagContent('description') ||
extractTagContent('description', tags) ||
extractPatchMessage(content) ||
'[untitled]'
let commit_title = commit_message.split('\n')[0]
let files = parseDiff(content)
let expand_files = files.map((file) => file.deletions + file.additions < 20)
@ -27,11 +35,6 @@ @@ -27,11 +35,6 @@
let expand_full_files = files.map((_) => false)
function extractTagContent(name: string): string | undefined {
let tag = tags.find((tag) => tag[0] === name)
return tag ? tag[1] : undefined
}
let isAddChange = (change: Change): change is AddChange =>
change.type == 'add'
let isDeleteChange = (change: Change): change is DeleteChange =>
@ -59,175 +62,191 @@ @@ -59,175 +62,191 @@
return undefined
}
}
let nevent = nip19.neventEncode({
id: event.id,
relays: event.relay ? [event.relay.url] : undefined,
})
let a_string = extractRepoAFromProposalEvent(event)
let pointer = a_string ? extractAReference(a_string) : undefined
let naddr = pointer ? nip19.naddrEncode(pointer) : undefined
</script>
<div class="">
<div class="flex rounded-t bg-base-300 p-1">
<article class="ml-2 flex-grow font-mono text-sm">
<ParsedContent content={commit_message} />
</article>
<div class="flex-none p-1 align-middle text-xs text-neutral">commit</div>
</div>
{#if preview}
<span>
Git Patch for <a class="opacity-50" href={`/e/${naddr}`}
>{pointer?.identifier}</a
>: <a href={`/e/${nevent}`}>{commit_title}</a> by
</span>
{:else}
<div class="">
<div class="flex rounded-t bg-base-300 p-1">
<article class="ml-2 flex-grow font-mono text-sm">
<ParsedContent content={commit_message} />
</article>
<div class="flex-none p-1 align-middle text-xs text-neutral">commit</div>
</div>
<div class="flex p-3">
<div class="flex-grow text-xs">Changes:</div>
<div class="flex-none text-right font-mono text-xs">
{commit_id_shorthand}
<div class="flex p-3">
<div class="flex-grow text-xs">Changes:</div>
<div class="flex-none text-right font-mono text-xs">
{commit_id_shorthand}
</div>
</div>
</div>
{#each files as file, index}
<div
class="my-2 border border-base-300 {expand_full_files[index]
? 'absolute left-0 z-10 w-screen bg-base-300 px-5'
: ''}"
>
<div class="flex w-full bg-base-200">
<button
class="flex shrink flex-grow p-3 text-sm"
on:click={() => {
if (expand_full_files[index]) {
{#each files as file, index}
<div
class="my-2 border border-base-300 {expand_full_files[index]
? 'absolute left-0 z-10 w-screen bg-base-300 px-5'
: ''}"
>
<div class="flex w-full bg-base-200">
<button
class="flex shrink flex-grow p-3 text-sm"
on:click={() => {
if (expand_full_files[index]) {
expand_full_files[index] = false
expand_files[index] = false
} else if (expand_files[index]) {
expand_full_files[index] = true
} else {
expand_files[index] = true
}
}}
><div class="shrink text-wrap text-left">
<span class="pr-3">{file.to || file.from}</span>
<span
class="text-middle flex-none align-middle font-mono text-xs opacity-70"
>{#if file.new}<span>created&nbsp;file</span
>&nbsp;{/if}{#if file.deleted}<span>deleted&nbsp;file</span
>&nbsp;{/if}{#if !file.deleted}<span class="text-success"
>+{file.additions}</span
>{/if}&nbsp;{#if !file.new}<span class="text-error"
>-{file.deletions}</span
>{/if}
</span>
</div>
<div class="flex-grow"></div>
</button>
<button
class="flex-none p-3 text-right text-xs opacity-40"
on:click={() => {
expand_files[index] = !expand_files[index]
expand_full_files[index] = false
expand_files[index] = false
} else if (expand_files[index]) {
expand_full_files[index] = true
} else {
expand_files[index] = true
}
}}
><div class="shrink text-wrap text-left">
<span class="pr-3">{file.to || file.from}</span>
<span
class="text-middle flex-none align-middle font-mono text-xs opacity-70"
>{#if file.new}<span>created&nbsp;file</span
>&nbsp;{/if}{#if file.deleted}<span>deleted&nbsp;file</span
>&nbsp;{/if}{#if !file.deleted}<span class="text-success"
>+{file.additions}</span
>{/if}&nbsp;{#if !file.new}<span class="text-error"
>-{file.deletions}</span
>{/if}
</span>
</div>
<div class="flex-grow"></div>
</button>
<button
class="flex-none p-3 text-right text-xs opacity-40"
on:click={() => {
expand_files[index] = !expand_files[index]
expand_full_files[index] = false
}}
>
{expand_files[index] ? 'colapse' : 'expand'}
</button>
<button
class="flex-none p-3 text-right text-xs opacity-40"
on:click={() => {
expand_full_files[index] = !expand_full_files[index]
if (expand_full_files[index]) expand_files[index] = true
}}
>
full
</button>
</div>
{#if expand_files[index]}
<div class="border-t-1 flex border-base-300 font-mono text-xs">
<div class="flex-full select-none text-right">
{#each file.chunks as chunk, index}
{#if index !== 0}
<div class="flex w-full bg-base-200">
<div
class="w-8 flex-none whitespace-pre pb-2 pr-2 pt-1 opacity-50"
>
...
</div>
</div>
{/if}
{#each chunk.changes as change, i}
<div class="flex w-full bg-base-100">
<div
class="w-8 flex-none whitespace-pre {change.type == 'add'
? 'bg-success/50'
: change.type == 'del'
? 'bg-error/50'
: 'bg-slate-500/20'} pr-2 opacity-50"
class:pt-3={index === 0 && i === 0}
class:pb-3={index === file.chunks.length - 1 &&
i === chunk.changes.length - 1}
>
{isAddChange(change) &&
i !== 0 &&
isDeleteChange(chunk.changes[i - 1])
? ' '
: extractChangeLine(change)}
</div>
</div>
{/each}
{/each}
</div>
<div class="flex-auto overflow-x-auto">
<div class="w-fit">
}}
>
{expand_files[index] ? 'colapse' : 'expand'}
</button>
<button
class="flex-none p-3 text-right text-xs opacity-40"
on:click={() => {
expand_full_files[index] = !expand_full_files[index]
if (expand_full_files[index]) expand_files[index] = true
}}
>
full
</button>
</div>
{#if expand_files[index]}
<div class="border-t-1 flex border-base-300 font-mono text-xs">
<div class="flex-full select-none text-right">
{#each file.chunks as chunk, index}
{#if index !== 0}
<div class="flex h-7 w-full bg-base-200"></div>
<div class="flex w-full bg-base-200">
<div
class="w-8 flex-none whitespace-pre pb-2 pr-2 pt-1 opacity-50"
>
...
</div>
</div>
{/if}
{#each chunk.changes as change, i}
<div class="flex w-full bg-base-100">
<div
class="w-full flex-grow whitespace-pre {change.type ==
'add'
? 'bg-success/20'
class="w-8 flex-none whitespace-pre {change.type == 'add'
? 'bg-success/50'
: change.type == 'del'
? 'bg-error/20'
: ''}"
? 'bg-error/50'
: 'bg-slate-500/20'} pr-2 opacity-50"
class:pt-3={index === 0 && i === 0}
class:pb-3={index === file.chunks.length - 1 &&
i === chunk.changes.length - 1}
>
{#if getFortmattedDiffHtml(change, (file.to || file.from)
?.split('.')
.pop() || '')}
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html getFortmattedDiffHtml(
change,
(file.to || file.from)?.split('.').pop() || ''
)}
{:else}
{change.type == 'normal'
? change.content
: change.content.substring(1)}
{/if}
{#if (change.type == 'normal' ? change.content : change.content.substring(1)).length === 0}
<!-- force empty line to have height -->
<span></span>
{/if}
{isAddChange(change) &&
i !== 0 &&
isDeleteChange(chunk.changes[i - 1])
? ' '
: extractChangeLine(change)}
</div>
</div>
{/each}
{/each}
</div>
<div class="flex-auto overflow-x-auto">
<div class="w-fit">
{#each file.chunks as chunk, index}
{#if index !== 0}
<div class="flex h-7 w-full bg-base-200"></div>
{/if}
{#each chunk.changes as change, i}
<div class="flex w-full bg-base-100">
<div
class="w-full flex-grow whitespace-pre {change.type ==
'add'
? 'bg-success/20'
: change.type == 'del'
? 'bg-error/20'
: ''}"
class:pt-3={index === 0 && i === 0}
class:pb-3={index === file.chunks.length - 1 &&
i === chunk.changes.length - 1}
>
{#if getFortmattedDiffHtml(change, (file.to || file.from)
?.split('.')
.pop() || '')}
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html getFortmattedDiffHtml(
change,
(file.to || file.from)?.split('.').pop() || ''
)}
{:else}
{change.type == 'normal'
? change.content
: change.content.substring(1)}
{/if}
{#if (change.type == 'normal' ? change.content : change.content.substring(1)).length === 0}
<!-- force empty line to have height -->
<span></span>
{/if}
</div>
</div>
{/each}
{/each}
</div>
</div>
</div>
{/if}
</div>
<!-- vertical padding for full width so that content retains it space -->
{#if expand_full_files[index]}
<div class="w-full whitespace-pre font-mono text-xs">
<span class="block p-3 text-sm"> </span>
{#each file.chunks as chunk, index}
{#if index !== 0}
<span class="block h-7 p-3"> </span>
{/if}
{#each chunk.changes as _, i}
<span
class="block"
class:pt-3={index === 0 && i === 0}
class:pb-3={index === file.chunks.length - 1 &&
i === chunk.changes.length - 1}
>&nbsp;
</span>
{/each}
{/each}
</div>
{/if}
</div>
<!-- vertical padding for full width so that content retains it space -->
{#if expand_full_files[index]}
<div class="w-full whitespace-pre font-mono text-xs">
<span class="block p-3 text-sm"> </span>
{#each file.chunks as chunk, index}
{#if index !== 0}
<span class="block h-7 p-3"> </span>
{/if}
{#each chunk.changes as _, i}
<span
class="block"
class:pt-3={index === 0 && i === 0}
class:pb-3={index === file.chunks.length - 1 &&
i === chunk.changes.length - 1}
>&nbsp;
</span>
{/each}
{/each}
</div>
{/if}
{/each}
</div>
{/each}
</div>
{/if}

19
src/lib/components/events/content/Repo.svelte

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
<script lang="ts">
import type { RepoEvent } from '$lib/components/repo/type'
import { eventToRepoEvent } from '$lib/stores/repos'
import type { NDKEvent } from '@nostr-dev-kit/ndk'
export let event: NDKEvent | RepoEvent
const isRepoEvent = (event: NDKEvent | RepoEvent): event is RepoEvent => {
return Object.keys(event).includes('web')
}
let repo = isRepoEvent(event) ? event : eventToRepoEvent(event)
</script>
{#if repo}
<span class="">
Git Repository: <a href={`/r/${repo.naddr}`}>{repo.name}</a> by
</span>
{/if}

41
src/lib/components/events/content/utils.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import type { NDKTag } from '@nostr-dev-kit/ndk'
import { nip19 } from 'nostr-tools'
import type { AddressPointer, EventPointer } from 'nostr-tools/lib/types/nip19'
import { last } from 'ramda'
export const TOPIC = 'topic'
@ -67,31 +68,29 @@ export const NOSTR_NOTE = 'nostr:note' @@ -67,31 +68,29 @@ export const NOSTR_NOTE = 'nostr:note'
type PartTypeNote = 'nostr:note'
export type ParsedNote = {
type: PartTypeNote
id: string
relays: string[]
data: EventPointer
}
export const NOSTR_NEVENT = 'nostr:nevent'
type PartTypeNevent = 'nostr:nevent'
export type ParsedNevent = {
type: PartTypeNevent
id: string
relays: string[]
data: EventPointer
}
export const NOSTR_NADDR = 'nostr:naddr'
type PartTypeNaddr = 'nostr:naddr'
export type ParsedNaddr = {
type: PartTypeNaddr
identifier: string
pubkey: string
kind: number
relays: string[]
data: AddressPointer
}
export type ParsedNostrLink = ParsedNpub | ParsedNprofile | ParsedNevent | ParsedNote | ParsedNaddr
export type ParsedNostrLink =
| ParsedNpub
| ParsedNprofile
| ParsedNevent
| ParsedNote
| ParsedNaddr
export const TEXT = 'text'
type PartTypeText = 'text'
@ -113,7 +112,11 @@ export const isParsedLink = (part: ParsedPart): part is ParsedLink => @@ -113,7 +112,11 @@ export const isParsedLink = (part: ParsedPart): part is ParsedLink =>
part.type == LINK
export const isParsedNostrLink = (part: ParsedPart): part is ParsedNostrLink =>
part.type == NOSTR_NPUB || part.type == NOSTR_NPROFILE || part.type == NOSTR_NEVENT || part.type == NOSTR_NOTE || part.type == NOSTR_NADDR
part.type == NOSTR_NPUB ||
part.type == NOSTR_NPROFILE ||
part.type == NOSTR_NEVENT ||
part.type == NOSTR_NOTE ||
part.type == NOSTR_NADDR
export const isParsedNpub = (part: ParsedPart): part is ParsedNpub =>
part.type == NOSTR_NPUB
@ -219,13 +222,13 @@ export const parseContent = (content: string, tags: NDKTag[]): ParsedPart[] => { @@ -219,13 +222,13 @@ export const parseContent = (content: string, tags: NDKTag[]): ParsedPart[] => {
return [bech32, { type: NOSTR_NPUB, hex: decoded.data.pubkey }]
}
if (decoded.type === 'note') {
return [bech32, { type: NOSTR_NOTE, id: decoded.data, relays: [] }]
return [bech32, { type: NOSTR_NOTE, data: { id: decoded.data } }]
}
if (decoded.type === 'nevent') {
return [bech32, { type: NOSTR_NEVENT, id: decoded.data.id, relays: decoded.data.relays || [] }]
return [bech32, { type: NOSTR_NEVENT, data: decoded.data }]
}
if (decoded.type === 'naddr') {
return [bech32, { ...decoded.data, type: NOSTR_NADDR, relays: decoded.data.relays || [] }]
return [bech32, { type: NOSTR_NADDR, data: decoded.data }]
}
} catch {}
}
@ -266,6 +269,14 @@ export const isCoverLetter = (s: string): boolean => { @@ -266,6 +269,14 @@ export const isCoverLetter = (s: string): boolean => {
return s.indexOf('PATCH 0/') > 0
}
export function extractTagContent(
name: string,
tags: NDKTag[]
): string | undefined {
const tag = tags.find((tag) => tag[0] === name)
return tag ? tag[1] : undefined
}
/** this doesn't work for all patch formats and options */
export const extractPatchMessage = (s: string): string | undefined => {
try {

24
src/lib/wrappers/EventCard.svelte

@ -5,7 +5,12 @@ @@ -5,7 +5,12 @@
import Patch from '$lib/components/events/content/Patch.svelte'
import ParsedContent from '$lib/components/events/content/ParsedContent.svelte'
import { defaults as user_defaults } from '$lib/components/users/type'
import { patch_kind, proposal_status_kinds } from '$lib/kinds'
import {
issue_kind,
patch_kind,
proposal_status_kinds,
repo_kind,
} from '$lib/kinds'
import { ensureUser } from '$lib/stores/users'
import type { NDKEvent } from '@nostr-dev-kit/ndk'
import { onDestroy } from 'svelte'
@ -14,9 +19,12 @@ @@ -14,9 +19,12 @@
extractPatchMessage,
isCoverLetter,
} from '$lib/components/events/content/utils'
import Repo from '$lib/components/events/content/Repo.svelte'
import IssuePreview from '$lib/components/events/content/IssuePreview.svelte'
export let event: NDKEvent
export let type: 'proposal' | 'issue' = 'proposal'
export let preview = false
let author = writable({ ...user_defaults })
let author_unsubsriber: Unsubscriber
@ -45,6 +53,18 @@ @@ -45,6 +53,18 @@
<EventWrapperLite author={$author} created_at={event.created_at}>
added to '{getDtag(event) || 'unknown'}' list by
</EventWrapperLite>
{:else if event.kind && event.kind == repo_kind}
<EventWrapperLite author={$author} created_at={event.created_at}>
<Repo {event} />
</EventWrapperLite>
{:else if preview && event.kind && event.kind === patch_kind}
<EventWrapperLite author={$author} created_at={event.created_at}>
<Patch {event} {preview} />
</EventWrapperLite>
{:else if preview && event.kind && event.kind === issue_kind}
<EventWrapperLite author={$author} created_at={event.created_at}>
<IssuePreview {event} />
</EventWrapperLite>
{:else}
<EventWrapper {type} author={$author} created_at={event.created_at} {event}>
{#if event.kind == patch_kind}
@ -54,7 +74,7 @@ @@ -54,7 +74,7 @@
tags={event.tags}
/>
{:else}
<Patch content={event.content} tags={event.tags} />
<Patch {event} />
{/if}
{:else if event.kind && proposal_status_kinds.includes(event.kind)}
<Status {type} status={event.kind} />

102
src/lib/wrappers/EventPreview.svelte

@ -1,58 +1,72 @@ @@ -1,58 +1,72 @@
<script lang="ts">
import EventWrapper from '$lib/components/events/EventWrapper.svelte'
import EventWrapperLite from '$lib/components/events/EventWrapperLite.svelte'
import Status from '$lib/components/events/content/Status.svelte'
import Patch from '$lib/components/events/content/Patch.svelte'
import ParsedContent from '$lib/components/events/content/ParsedContent.svelte'
import { defaults as user_defaults } from '$lib/components/users/type'
import { patch_kind, proposal_status_kinds } from '$lib/kinds'
import { ensureUser } from '$lib/stores/users'
import { NDKRelaySet, type NDKEvent } from '@nostr-dev-kit/ndk'
import { onDestroy, onMount } from 'svelte'
import { get, writable, type Unsubscriber, type Writable } from 'svelte/store'
import {
extractPatchMessage,
isCoverLetter,
isParsedNaddr,
type ParsedNaddr,
type ParsedNevent,
type ParsedNote,
} from '$lib/components/events/content/utils'
import { onMount } from 'svelte'
import { get, writable, type Writable } from 'svelte/store'
import { base_relays, ndk } from '$lib/stores/ndk'
import EventCard from './EventCard.svelte'
import type {
AddressPointer,
EventPointer,
} from 'nostr-tools/lib/types/nip19'
import { repo_kind } from '$lib/kinds'
import { ensureRepo } from '$lib/stores/repos'
import EventWrapperLite from '$lib/components/events/EventWrapperLite.svelte'
import Repo from '$lib/components/events/content/Repo.svelte'
export let parsed_nostr_ref: ParsedNaddr | ParsedNevent | ParsedNote
export let pointer: AddressPointer | EventPointer
let cannot_find_event = false;
let cannot_find_event = false
let event: Writable<undefined | NDKEvent> = writable(undefined)
const isAddressPointer = (
pointer: AddressPointer | EventPointer
): pointer is AddressPointer => {
return Object.keys(pointer).includes('identifier')
}
let is_repo = isAddressPointer(pointer) && pointer.kind == repo_kind
let repo =
is_repo && isAddressPointer(pointer)
? ensureRepo(`${pointer.kind}:${pointer.pubkey}:${pointer.identifier}`)
: undefined
onMount(() => {
let sub = ndk.subscribe(
isParsedNaddr(parsed_nostr_ref) ? {
'#a': [`${parsed_nostr_ref.kind}:${parsed_nostr_ref.pubkey}:${parsed_nostr_ref.identifier}`],
} :
{ ids: [parsed_nostr_ref.id] },
{closeOnEose: true},
NDKRelaySet.fromRelayUrls([ ...base_relays, ...parsed_nostr_ref.relays ], ndk)
)
if (!is_repo) {
let sub = ndk.subscribe(
isAddressPointer(pointer)
? {
'#a': [`${pointer.kind}:${pointer.pubkey}:${pointer.identifier}`],
}
: { ids: [pointer.id] },
{ closeOnEose: true },
NDKRelaySet.fromRelayUrls(
pointer.relays ? [...base_relays, ...pointer.relays] : base_relays,
ndk
)
)
sub.on('event', (e: NDKEvent) => {
event.set(e)
})
sub.on('event', (e: NDKEvent) => {
event.set(e)
})
sub.on('eose', () => {
if (!get(event)) cannot_find_event = true
})
sub.on('eose', () => {
if (!get(event)) cannot_find_event = true
})
}
})
</script>
<div class="card shadow-xl border border-base-400 p-2 pt-0 my-3">
{#if $event && $event.pubkey}
<EventCard event={$event} />
{:else if cannot_find_event}
cannot find event
{:else}
loading...
{/if}
</div>
<div class="card my-3 border border-base-400 shadow-xl">
{#if repo && $repo}
<EventWrapperLite author={$repo?.author} created_at={$repo?.created_at}>
<Repo event={$repo} />
</EventWrapperLite>
{:else if $event && $event.pubkey}
<div class="p-2 pt-0">
<EventCard event={$event} preview={true} />
</div>
{:else if cannot_find_event}
<div class="m-3 text-center text-sm">cannot find event</div>
{:else}
<div class="m-3 text-center text-sm">loading...</div>
{/if}
</div>

Loading…
Cancel
Save