refactor: remove legacy annotate mode — transcription replaces it
Some checks failed
CI / Unit & Component Tests (push) Has been cancelled
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Backend Unit Tests (pull_request) Failing after 4m26s
CI / Unit & Component Tests (pull_request) Failing after 14m40s
CI / E2E Tests (pull_request) Failing after 1h26m51s

The yellow annotation+comment system is now redundant. Transcription
blocks handle the same use case (mark region → discuss) but better,
because they also produce a transcription.

Removed:
- annotateMode state and all wiring through page/topbar/viewer/pdfviewer
- Annotate/Stop annotate buttons from DocumentTopBar
- AnnotateHintStrip import and rendering
- AnnotationSidePanel from document detail page
- canAnnotate prop from DocumentTopBar
- Color picker from PdfViewer
- Comment count badges and loadCommentCounts from PdfViewer
- Delete button from AnnotationLayer (blocks own annotation lifecycle)
- dimColor prop from AnnotationLayer

Simplified:
- AnnotationLayer: only canDraw + color + onDraw + onAnnotationClick
- PdfViewer: only draws in transcribeMode with turquoise
- Clicking annotation in transcribe mode scrolls to corresponding block
- canComment derived from canWrite (no longer needs canAnnotate)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-05 21:17:27 +02:00
parent 8c26876345
commit f3c29ffe58
6 changed files with 76 additions and 378 deletions

View File

@@ -1,25 +1,14 @@
<script lang="ts">
import { onMount } from 'svelte';
import { page } from '$app/state';
import DocumentTopBar from '$lib/components/DocumentTopBar.svelte';
import DocumentViewer from '$lib/components/DocumentViewer.svelte';
import AnnotationSidePanel from '$lib/components/AnnotationSidePanel.svelte';
import TranscriptionEditView from '$lib/components/TranscriptionEditView.svelte';
import type { TranscriptionBlockData } from '$lib/types';
let { data } = $props();
const targetCommentId = $derived(page.url.searchParams.get('commentId'));
const targetAnnotationId = $derived(page.url.searchParams.get('annotationId'));
const doc = $derived(data.document);
const canWrite = $derived(data.canWrite ?? false);
const canComment = $derived((data.canAnnotate || data.canWrite) ?? false);
const canAdmin = $derived(
(data.user?.groups as Array<{ permissions: string[] }> | undefined)?.some((g) =>
g.permissions.includes('ADMIN')
) ?? false
);
const currentUserId = $derived((data.user?.id as string | undefined) ?? null);
// ── File loading ──────────────────────────────────────────────────────────────
@@ -57,12 +46,10 @@ async function loadFile(id: string) {
}
}
// ── Mode state (mutually exclusive) ──────────────────────────────────────────
// ── Mode state ───────────────────────────────────────────────────────────────
let annotateMode = $state(false);
let transcribeMode = $state(false);
let activeAnnotationId = $state<string | null>(null);
let activeAnnotationPage = $state<number | null>(null);
// ── Transcription blocks ─────────────────────────────────────────────────────
@@ -137,6 +124,18 @@ function handleBlockFocus(blockId: string) {
}
}
function handleAnnotationClick(annotationId: string) {
activeAnnotationId = annotationId;
// In transcribe mode, focus the block that owns this annotation
if (transcribeMode) {
const block = transcriptionBlocks.find((b) => b.annotationId === annotationId);
if (block) {
const el = document.querySelector(`[data-block-id="${block.id}"]`);
el?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
}
// Load blocks when transcribe mode is entered
$effect(() => {
if (transcribeMode) {
@@ -151,10 +150,6 @@ let navHeight = $state(0);
onMount(() => {
navHeight = document.querySelector('header')?.getBoundingClientRect().height ?? 0;
if (targetAnnotationId) {
activeAnnotationId = targetAnnotationId;
}
if (doc?.id) {
localStorage.setItem(
'familienarchiv.lastVisited',
@@ -163,13 +158,8 @@ onMount(() => {
}
function onKeyDown(e: KeyboardEvent) {
if (e.key === 'Escape') {
if (transcribeMode) {
transcribeMode = false;
} else if (activeAnnotationId) {
activeAnnotationId = null;
activeAnnotationPage = null;
}
if (e.key === 'Escape' && transcribeMode) {
transcribeMode = false;
}
}
document.addEventListener('keydown', onKeyDown);
@@ -189,9 +179,7 @@ onMount(() => {
<DocumentTopBar
doc={doc}
canWrite={canWrite}
canAnnotate={data.canAnnotate ?? false}
fileUrl={fileUrl}
bind:annotateMode={annotateMode}
bind:transcribeMode={transcribeMode}
/>
@@ -202,39 +190,19 @@ onMount(() => {
fileUrl={fileUrl}
isLoading={isLoading}
error={fileError}
bind:annotateMode={annotateMode}
transcribeMode={transcribeMode}
bind:activeAnnotationId={activeAnnotationId}
bind:activeAnnotationPage={activeAnnotationPage}
onAnnotationClick={(id) => {
activeAnnotationId = id;
}}
onAnnotationClick={handleAnnotationClick}
onTranscriptionDraw={createBlockFromDraw}
/>
</div>
{#if !transcribeMode}
<AnnotationSidePanel
documentId={doc.id}
activeAnnotationId={activeAnnotationId}
activeAnnotationPage={activeAnnotationPage}
canComment={canComment}
currentUserId={currentUserId}
canAdmin={canAdmin}
targetCommentId={targetAnnotationId ? targetCommentId : null}
onClose={() => {
activeAnnotationId = null;
activeAnnotationPage = null;
}}
/>
{/if}
{#if transcribeMode}
<div class="w-[400px] shrink-0 border-l border-line lg:w-[480px]">
<TranscriptionEditView
documentId={doc.id}
blocks={transcriptionBlocks}
canComment={canComment}
canComment={canWrite}
currentUserId={currentUserId}
onBlockFocus={handleBlockFocus}
onSaveBlock={saveBlock}