{#snippet embedBadge(embed: AppBskyEmbeds)} {getEmbedText(embed.$type!)} {/snippet} {#if mini}
{#await post} loading... {:then post} {#if post.ok} {@const record = post.value.record}
scrollToAndPulse(post.value.uri)} class="select-none hover:cursor-pointer hover:underline" > @{handle}: {#if record.embed} {@render embedBadge(record.embed)} {/if} {record.text}
{:else} {post.error} {/if} {/await}
{:else} {#await post}

loading post...

{:then post} {#if post.ok} {@const record = post.value.record}
{#await client.getProfile(did)} {handle} {:then profile} {#if profile.ok} {@const profileValue = profile.value} {profileValue.displayName}(@{handle}) {:else} {handle} {/if} {/await} ยท {getRelativeTime(new Date(record.createdAt))}

{record.text} {#if isOnPostComposer && record.embed} {@render embedBadge(record.embed)} {/if}

{#if !isOnPostComposer && record.embed} {@const embed = record.embed}
{@render postEmbed(embed)}
{/if} {#if !isOnPostComposer} {@const backlinks = postActions.get(`${selectedDid!}:${post.value.uri}`)} {@render postControls(post.value, backlinks)} {/if}
{:else}

error: {post.error}

{/if} {/await} {/if} {#snippet postEmbed(embed: AppBskyEmbeds)} {#snippet embedMedia( embed: AppBskyEmbedImages.Main | AppBskyEmbedVideo.Main | AppBskyEmbedExternal.Main )} {#if embed.$type === 'app.bsky.embed.images'} {#each embed.images as image (image.image)} {#if isBlob(image.image)} {image.alt} {/if} {/each} {:else if embed.$type === 'app.bsky.embed.video'} {#if isBlob(embed.video)} {#await didDoc then didDoc} {#if didDoc.ok} {/if} {/await} {/if} {/if} {/snippet} {#snippet embedPost(uri: ResourceUri)} {#if quoteDepth < 2} {@const parsedUri = expect(parseCanonicalResourceUri(uri))} {#if !(did === parsedUri.repo && rkey === parsedUri.rkey)} {:else} you think you're funny with that recursive quote but i'm onto you {/if} {:else} {@render embedBadge(embed)} {/if} {/snippet} {#if embed.$type === 'app.bsky.embed.images' || embed.$type === 'app.bsky.embed.video'} {@render embedMedia(embed)} {:else if embed.$type === 'app.bsky.embed.record'} {@render embedPost(embed.record.uri)} {:else if embed.$type === 'app.bsky.embed.recordWithMedia'}
{@render embedPost(embed.record.record.uri)} {@render embedMedia(embed.media)}
{/if} {/snippet} {#snippet postControls(post: PostWithUri, backlinks?: PostActions)} {#snippet control( name: string, icon: string, onClick: (e: MouseEvent) => void, isFull?: boolean, hasSolid?: boolean )} {/snippet}
{#snippet label( name: string, icon: string, onClick: (link: Backlink | null | undefined) => void, backlink?: Backlink | null, hasSolid?: boolean )} {@render control(name, icon, () => onClick(backlink), backlink ? true : false, hasSolid)} {/snippet} {@render label('reply', 'heroicons:chat-bubble-left', () => { onReply?.(post); })} {@render label( 'repost', 'heroicons:arrow-path-rounded-square-20-solid', async (link) => { if (link === undefined) return; postActions.set(`${selectedDid!}:${aturi}`, { ...backlinks!, repost: await toggleLink(link, 'app.bsky.feed.repost') }); }, backlinks?.repost )} {@render label('quote', 'heroicons:paper-clip-20-solid', () => { onQuote?.(post); })} {@render label( 'like', 'heroicons:star', async (link) => { if (link === undefined) return; postActions.set(`${selectedDid!}:${aturi}`, { ...backlinks!, like: await toggleLink(link, 'app.bsky.feed.like') }); }, backlinks?.like, true )}
{@render dropdownItem('heroicons:link-20-solid', 'copy link to post', () => navigator.clipboard.writeText(`${$settings.socialAppUrl}/profile/${did}/post/${rkey}`) )} {@render dropdownItem('heroicons:link-20-solid', 'copy at uri', () => navigator.clipboard.writeText(post.uri) )} {@render dropdownItem('heroicons:clipboard-20-solid', 'copy post text', () => navigator.clipboard.writeText(post.record.text) )} {#if actionClient}
{@render dropdownItem( deleteState === 'confirm' ? 'heroicons:check-20-solid' : 'heroicons:trash-20-solid', deleteState === 'confirm' ? 'are you sure?' : 'delete post', deletePost, false, deleteState === 'confirm' ? 'text-red-500' : '' )} {/if} {#snippet trigger()}
{@render control('actions', 'heroicons:ellipsis-horizontal-16-solid', (e) => { e.stopPropagation(); actionsOpen = !actionsOpen; actionsPos = { x: 0, y: 0 }; })}
{/snippet}
{/snippet} {#snippet dropdownItem( icon: string, label: string, onClick: () => void, autoClose: boolean = true, extraClass: string = '' )} {/snippet}