Files
plspace/src/routes/Quotes.svelte
T
2026-07-30 19:45:40 +09:00

91 lines
2.7 KiB
Svelte

<script lang="ts">
/** Paginated posts that quote one source entry. */
import { untrack } from 'svelte'
import type { Status } from '$lib/api/types'
import { useAppServices } from '$lib/app-services'
import { Feed } from '$lib/stores/feed.svelte'
import { useTimelineRefresh } from '$lib/timeline-refresh'
import Module from '$components/common/Module.svelte'
import BlogEntry from '$components/blog/BlogEntry.svelte'
import BlogList from '$components/blog/BlogList.svelte'
interface Props {
id: string
}
let { id }: Props = $props()
const { endpoints, session } = useAppServices()
const timelineRefresh = useTimelineRefresh()
let source = $state<Status | null>(null)
let sourceError = $state<string | null>(null)
let sourceLoading = $state(true)
let loadGeneration = 0
let feed = $state<Feed<Status>>(
new Feed<Status>(async () => ({ items: [], links: {} })),
)
$effect(() => {
const currentId = id
const generation = ++loadGeneration
source = null
sourceError = null
sourceLoading = true
feed = new Feed<Status>((cursor) => endpoints.fetchQuotes(session.api, currentId, cursor))
untrack(() => {
void feed.reload()
void loadSource(currentId, generation)
})
return () => {
if (generation === loadGeneration) loadGeneration += 1
}
})
$effect(() => timelineRefresh?.register(() => void feed.refresh()))
async function loadSource(currentId: string, generation: number): Promise<void> {
try {
const found = await endpoints.fetchStatus(session.api, currentId)
if (generation === loadGeneration && id === currentId) {
source = found
document.title = 'Quotes | plspace'
}
} catch (cause) {
if (generation === loadGeneration) {
sourceError = cause instanceof Error ? cause.message : 'Could not load the original entry.'
}
} finally {
if (generation === loadGeneration) sourceLoading = false
}
}
</script>
<div class="page quotes-page">
<h1 class="page-title">Quotes of this Blog Entry</h1>
<div class="layout--single">
<Module title="Original Entry" variant="band">
{#if sourceLoading}
<p class="loading-note">Loading original entry&hellip;</p>
{:else if sourceError}
<p class="error-note" role="alert">{sourceError}</p>
{:else if source}
<BlogEntry
status={source}
compact
onupdate={(updated) => (source = updated)}
/>
{/if}
</Module>
<Module title="Entries quoting this" variant="band">
<BlogList
{feed}
emptyText="Nobody has quoted this entry yet."
label="View More Quotes"
longFormDate
/>
</Module>
</div>
</div>