mirror of
https://git.shipoclu.com/moon/plspace.git
synced 2026-08-13 02:42:30 +00:00
102 lines
3.1 KiB
Svelte
102 lines
3.1 KiB
Svelte
<script lang="ts">
|
|
/**
|
|
* A timeline, presented as a blog: "My Blog" (home), "This Server" (local),
|
|
* "The Whole Network" (federated), or a hashtag.
|
|
*/
|
|
import { untrack } from 'svelte'
|
|
import type { Status } from '$lib/api/types'
|
|
import type { TimelineKind } from '$lib/api/endpoints'
|
|
import { useAppServices } from '$lib/app-services'
|
|
import { Feed } from '$lib/stores/feed.svelte'
|
|
import { instanceDomain } from '$lib/api/endpoints'
|
|
import { useTimelineRefresh } from '$lib/timeline-refresh'
|
|
import Module from '$components/common/Module.svelte'
|
|
import TabBar from '$components/common/TabBar.svelte'
|
|
import BlogList from '$components/blog/BlogList.svelte'
|
|
import Composer from '$components/blog/Composer.svelte'
|
|
|
|
interface Props {
|
|
kind: TimelineKind
|
|
tag?: string
|
|
}
|
|
|
|
let { kind, tag }: Props = $props()
|
|
|
|
const { endpoints, session } = useAppServices()
|
|
const timelineRefresh = useTimelineRefresh()
|
|
let feed = $state<Feed<Status>>(new Feed<Status>(async () => ({ items: [], links: {} })))
|
|
|
|
const domain = $derived(session.host ? instanceDomain(session.instance, session.host) : '')
|
|
|
|
const title = $derived(
|
|
kind === 'home'
|
|
? 'My Blog'
|
|
: kind === 'local'
|
|
? `Blogs on ${domain}`
|
|
: kind === 'tag'
|
|
? `#${tag}`
|
|
: 'The Whole Network',
|
|
)
|
|
|
|
const tabs = $derived([
|
|
...(session.signedIn ? [{ label: 'My Blog', href: '#/timeline/home' }] : []),
|
|
{ label: 'This Server', href: '#/timeline/local' },
|
|
{ label: 'Whole Network', href: '#/timeline/public' },
|
|
])
|
|
|
|
const currentTab = $derived(kind === 'tag' ? '' : `#/timeline/${kind}`)
|
|
|
|
$effect(() => {
|
|
const currentKind = kind
|
|
const currentTag = tag
|
|
const host = session.host
|
|
const authed = session.signedIn
|
|
if (!host) return
|
|
|
|
untrack(() => {
|
|
// Home needs a token; fall back rather than showing a 401.
|
|
const resolved: TimelineKind = currentKind === 'home' && !authed ? 'local' : currentKind
|
|
feed = new Feed<Status>((cursor) =>
|
|
endpoints.fetchTimeline(session.api, resolved, cursor, { tag: currentTag }),
|
|
)
|
|
void feed.reload()
|
|
document.title = `${title} | plspace`
|
|
})
|
|
})
|
|
|
|
$effect(() => timelineRefresh?.register(() => void feed.reload()))
|
|
</script>
|
|
|
|
<div class="page timeline-page" data-timeline={kind} data-tag={tag ?? ''}>
|
|
<h1 class="page-title">{title}</h1>
|
|
|
|
{#if kind !== 'tag'}
|
|
<TabBar {tabs} current={currentTab} label="Timelines" />
|
|
{/if}
|
|
|
|
{#if kind === 'home' && !session.signedIn}
|
|
<p class="notice">
|
|
You're browsing as a guest, so this is <strong>{domain}</strong>'s local timeline.
|
|
<a href="#/login">Sign in</a> to read your own.
|
|
</p>
|
|
{/if}
|
|
|
|
<div class="layout--single">
|
|
{#if kind === 'home' && session.signedIn}
|
|
<Module title="Post a new entry">
|
|
<Composer onposted={(status) => feed.prepend(status)} />
|
|
</Module>
|
|
{/if}
|
|
|
|
<Module title={title} variant="band">
|
|
<BlogList
|
|
{feed}
|
|
emptyText={kind === 'tag'
|
|
? `Nobody has posted with #${tag} that this server knows about.`
|
|
: 'There are no Blog Entries yet.'}
|
|
longFormDate
|
|
/>
|
|
</Module>
|
|
</div>
|
|
</div>
|