Files
familienarchiv/frontend/src/lib/document/DocumentViewer.svelte
Marcel 1e656d2db4 refactor: move document transcription, annotation, viewer sub-packages
- transcription/: TranscriptionBlock, Column, EditView, PanelHeader, ReadView,
  Section + transcriptionMarkers, blockConflictMerge, saveBlockWithConflictRetry
  + useBlockAutoSave, useBlockDragDrop hooks
- annotation/: AnnotationLayer, AnnotationShape, AnnotationEditOverlay
- viewer/: PdfViewer, PdfControls + useFileLoader, usePdfRenderer hooks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:01:39 +02:00

116 lines
3.2 KiB
Svelte

<script lang="ts">
import { m } from '$lib/paraglide/messages.js';
import PdfViewer from '$lib/document/viewer/PdfViewer.svelte';
type Doc = {
id: string;
filePath?: string | null;
contentType?: string | null;
fileHash?: string | null;
};
type DrawRect = { x: number; y: number; width: number; height: number; pageNumber: number };
type Props = {
doc: Doc;
fileUrl: string;
isLoading: boolean;
error: string;
transcribeMode?: boolean;
blockNumbers?: Record<string, number>;
annotationReloadKey?: number;
activeAnnotationId: string | null;
annotationsDimmed?: boolean;
flashAnnotationId?: string | null;
onAnnotationClick: (id: string) => void;
onTranscriptionDraw?: (rect: DrawRect) => void;
onDeleteAnnotationRequest?: (annotationId: string) => void;
};
let {
doc,
fileUrl,
isLoading,
error,
transcribeMode = false,
blockNumbers = {},
annotationReloadKey = 0,
activeAnnotationId = $bindable(),
annotationsDimmed = false,
flashAnnotationId = null,
onAnnotationClick,
onTranscriptionDraw,
onDeleteAnnotationRequest
}: Props = $props();
</script>
<div class="absolute inset-0 bg-pdf-bg">
{#if isLoading}
<div class="flex h-full flex-col items-center justify-center text-accent">
<svg
class="mb-4 h-8 w-8 animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
<span class="font-sans text-sm tracking-wide">{m.doc_loading()}</span>
</div>
{:else if error}
<div class="flex h-full flex-col items-center justify-center px-4 text-center text-ink-3">
<p class="mb-2 font-serif">{error}</p>
{#if doc.filePath}
<a
href="/api/documents/{doc.id}/file"
target="_blank"
class="text-sm underline hover:text-white"
>
{m.doc_download_link()}
</a>
{/if}
</div>
{:else if !doc.filePath}
<div class="flex h-full flex-col items-center justify-center text-ink-3">
<div class="mb-6 rounded-full bg-surface/5 p-8">
<img
src="/degruyter-icons/Simple/Medium-24px/SVG/Action/PDF-Document-MD.svg"
alt=""
aria-hidden="true"
class="h-12 w-12 opacity-50 invert"
/>
</div>
<p class="font-sans text-sm tracking-wide uppercase">{m.doc_no_scan()}</p>
</div>
{:else if fileUrl && doc.contentType?.startsWith('application/pdf')}
<PdfViewer
url={fileUrl}
documentId={doc.id}
transcribeMode={transcribeMode}
blockNumbers={blockNumbers}
annotationReloadKey={annotationReloadKey}
bind:activeAnnotationId={activeAnnotationId}
annotationsDimmed={annotationsDimmed}
flashAnnotationId={flashAnnotationId}
onAnnotationClick={onAnnotationClick}
onTranscriptionDraw={onTranscriptionDraw}
onDeleteAnnotationRequest={onDeleteAnnotationRequest}
documentFileHash={doc.fileHash ?? null}
/>
{:else if fileUrl}
<div class="flex h-full w-full items-center justify-center overflow-auto p-8">
<img
src={fileUrl}
alt={m.doc_image_alt()}
class="max-h-full max-w-full object-contain shadow-2xl"
/>
</div>
{/if}
</div>