Files
flotilla/src/app/components/ThreadPost.svelte
T
hodlbod 9df8cee501 Migrate to new @welshman/domain + instance-based @welshman/app API
Adopts the rewritten welshman API: the removed @welshman/util helpers
(Profile/List/Room/Handler/Encryptable) are now Reader/Builder classes in
@welshman/domain, and @welshman/app dropped its global singletons for an App
instance + app.use(Plugin) registry.

- src/app/welshman.ts is now the app bootstrap + session-state module (one shared
  App instance, multi-account sessions/login, app-wide reactive views) rather than
  a compat shim re-exporting the old globals.
- Rewrote ~100 callers to use app.use(Plugin) directly (thunks, profiles, relays,
  rooms, zaps, tags, wot, feeds, sync); thunk helpers are now thunk methods.
- Added @welshman/domain dependency.
- Resolved residual gaps (storage hydration via plugin.onItem/wrapManager/Plaintext,
  relay-list mutators, search-relay list, outbox #d filter).

Best-effort: no toolchain/linking available, so this is not build- or
type-checked. Remaining judgment calls are flagged with TODO(welshman-migration).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BsMjvv7krpZeHK1Njeneru
2026-06-20 14:55:06 +00:00

95 lines
3.6 KiB
Svelte

<script lang="ts">
import {formatTimestamp} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util"
import {COMMENT, displayNip05} from "@welshman/util"
import {Handles, Profiles} from "@welshman/app"
import {app} from "@app/welshman"
import Reply from "@assets/icons/reply-2.svg?dataurl"
import LinkRound from "@assets/icons/link-round.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte"
import ProfileCircle from "@app/components/ProfileCircle.svelte"
import ProfileDetail from "@app/components/ProfileDetail.svelte"
import NoteContent from "@app/components/NoteContent.svelte"
import Content from "@app/components/Content.svelte"
import CommentActions from "@app/components/CommentActions.svelte"
import ThreadActions from "@app/components/ThreadActions.svelte"
import {makeEventPermalink} from "@app/routes"
import {pushModal} from "@app/modal"
import {clip} from "@app/toast"
type Props = {
url: string
event: TrustedEvent
threadPubkey: string
onReply: (event: TrustedEvent) => void
}
const {url, event, threadPubkey, onReply}: Props = $props()
const profileDisplay = app.use(Profiles).display(event.pubkey, [url]).$
const handle = app.use(Handles).forPubkey(event.pubkey).$
const isOp = event.pubkey === threadPubkey
const isComment = event.kind === COMMENT
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey, url})
const copyPermalink = () => clip(makeEventPermalink(event, url))
const reply = () => onReply(event)
</script>
<article
id="post-{event.id}"
data-event={event.id}
class="border-b border-base-content/15 bg-base-100">
<div class="flex flex-col md:flex-row">
<aside
class="flex shrink-0 flex-row items-center gap-3 border-b border-base-content/10 bg-base-200/50 p-3 md:w-40 md:flex-col md:items-center md:border-b-0 md:border-r md:p-4 md:text-center">
<Button onclick={openProfile}>
<ProfileCircle pubkey={event.pubkey} {url} size={10} class="md:size-14" />
</Button>
<div class="flex min-w-0 flex-col gap-1 md:items-center">
<Button onclick={openProfile} class="text-bold ellipsize text-sm">
{$profileDisplay}
</Button>
{#if $handle}
<span class="ellipsize text-xs opacity-75">{displayNip05($handle?.nip05)}</span>
{/if}
{#if isOp}
<span class="badge badge-primary badge-sm">OP</span>
{/if}
</div>
</aside>
<div class="flex min-w-0 grow flex-col">
<div
class="flex flex-wrap items-center justify-between gap-2 border-b border-base-content/10 bg-base-200/40 px-3 py-2 text-xs sm:px-4 sm:text-sm">
<span class="opacity-75">{formatTimestamp(event.created_at)}</span>
<Button class="btn btn-ghost btn-xs h-auto min-h-0 gap-1 px-1 py-0" onclick={copyPermalink}>
<Icon icon={LinkRound} size={3} />
Permalink
</Button>
</div>
<div class="px-3 py-4 sm:px-4">
{#if isComment}
<Content showEntire {event} {url} />
{:else}
<NoteContent showEntire {event} {url} />
{/if}
</div>
<div
class="flex shrink-0 flex-col gap-2 border-t border-base-content/10 bg-base-200/20 px-3 py-3 sm:flex-row sm:items-center sm:justify-between sm:px-4">
<Button class="btn btn-neutral btn-xs w-fit gap-1" onclick={reply}>
<Icon icon={Reply} size={4} />
Reply
</Button>
{#if isComment}
<CommentActions segment="threads" {event} {url} />
{:else}
<ThreadActions {event} {url} />
{/if}
</div>
</div>
</div>
</article>