Files
sendewerk/src/routes/heinzlive/[token]/+page.svelte
T
2026-10-23 21:33:15 +02:00

76 lines
2.3 KiB
Svelte

<script lang="ts">
import { page } from '$app/state';
import { onMount, untrack } from 'svelte';
import PresentationDisplay from '#lib/components/PresentationDisplay.svelte';
import type { PageProps } from './$types';
let { data }: PageProps = $props();
let view = $state(untrack(() => data.view ?? { revision: -1, content: null }));
let connection = $state<'connected' | 'waiting' | 'interrupted'>(
untrack(() => (data.view ? 'connected' : 'waiting'))
);
onMount(() => {
let stopped = false;
let timer: ReturnType<typeof setTimeout>;
async function refresh() {
try {
const response = await fetch(`/heinzlive/${page.params.token}/state`, {
headers: { Accept: 'application/json' },
cache: 'no-store'
});
if (!response.ok) throw new Error('STATE_UNAVAILABLE');
const next = await response.json();
if (next.revision !== view.revision) view = next;
connection = 'connected';
} catch {
connection = 'interrupted';
}
if (!stopped) timer = setTimeout(refresh, connection === 'interrupted' ? 3000 : 1000);
}
async function connect() {
const accessKey = decodeURIComponent(location.hash.slice(1));
if (accessKey) {
const response = await fetch(`/heinzlive/${data.channelId}/access`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ key: accessKey })
});
if (!response.ok) {
connection = 'interrupted';
return;
}
}
timer = setTimeout(refresh, 0);
}
void connect();
return () => {
stopped = true;
clearTimeout(timer);
};
});
</script>
<svelte:head>
<title>heinzlive</title>
<meta name="robots" content="noindex, nofollow, noarchive" />
</svelte:head>
<main class:empty={!view.content} class="heinzlive-output">
<div class="output-connection sr-only" class:problem={connection === 'interrupted'} role="status">
<span></span>{connection === 'interrupted' ? 'Verbindung unterbrochen' : 'Verbunden'}
</div>
{#if view.content}
{#key view.revision}
<PresentationDisplay
content={view.content}
imageSrc={view.content.images.length
? view.content.mode === 'text'
? `/heinzlive/${page.params.token}/media`
: `/heinzlive/${page.params.token}/media/${view.content.images[0].id}`
: `/heinzlive/${page.params.token}/preview-image`}
/>
{/key}
{/if}
</main>