fix(transcription): always show comment list, compose box on demand
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 / Unit & Component Tests (pull_request) Has been cancelled
CI / Backend Unit Tests (pull_request) Has been cancelled
CI / E2E Tests (pull_request) Has been cancelled

Comments were only visible after clicking "Kommentieren". Now:
- Comment list always renders (CommentThread with loadOnMount=true)
- Compose box hidden by default (showCompose prop on CommentThread)
- Clicking "Kommentieren" sets commentOpen=true → shows compose box
- Closing hides compose box but comments remain visible

This separates "viewing comments" (always) from "writing a comment"
(on demand via Kommentieren button).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-05 22:02:15 +02:00
parent 6475ebcc60
commit be4f1ed73b
4 changed files with 17 additions and 60 deletions

View File

@@ -17,6 +17,7 @@ type Props = {
canAdmin: boolean;
targetCommentId?: string | null;
quotedText?: string | null;
showCompose?: boolean;
onCountChange?: (count: number) => void;
};
@@ -31,6 +32,7 @@ let {
canAdmin,
targetCommentId = null,
quotedText = null,
showCompose = true,
onCountChange
}: Props = $props();
@@ -357,7 +359,7 @@ onMount(async () => {
{/each}
<!-- New top-level comment -->
{#if canComment}
{#if canComment && showCompose}
<div class={comments.length > 0 ? 'border-t border-line pt-4' : ''}>
<div class="flex flex-col gap-2">
<MentionEditor

View File

@@ -14,7 +14,6 @@ type Props = {
saveState: SaveState;
canComment: boolean;
currentUserId: string | null;
commentCount: number;
onTextChange: (text: string) => void;
onFocus: () => void;
onDeleteClick: () => void;
@@ -31,7 +30,6 @@ let {
saveState,
canComment,
currentUserId,
commentCount,
onTextChange,
onFocus,
onDeleteClick,
@@ -39,7 +37,7 @@ let {
}: Props = $props();
let localText = $state(text);
let commentOpen = $state(commentCount > 0);
let commentOpen = $state(false);
let selectedQuote = $state<string | null>(null);
let textareaEl = $state<HTMLTextAreaElement | null>(null);
@@ -199,34 +197,18 @@ function captureSelectionAndOpenComments() {
</div>
</div>
<!-- Comment thread (expandable) -->
{#if commentOpen}
<div class="mt-3 border-t border-line pt-3">
<div class="mb-2 flex items-center justify-between">
<span class="font-sans text-xs font-semibold text-ink-2">
{m.comment_section_title()}
</span>
<button
type="button"
class="font-sans text-xs text-ink-3 transition-colors hover:text-ink"
onclick={() => {
commentOpen = false;
selectedQuote = null;
}}
>
{m.comment_panel_close()}
</button>
</div>
<CommentThread
documentId={documentId}
blockId={blockId}
loadOnMount={true}
canComment={canComment}
currentUserId={currentUserId}
canAdmin={false}
quotedText={selectedQuote}
/>
</div>
{/if}
<!-- Comment thread — list always visible, compose toggled by Kommentieren -->
<div class="mt-3 border-t border-line pt-3">
<CommentThread
documentId={documentId}
blockId={blockId}
loadOnMount={true}
canComment={canComment}
currentUserId={currentUserId}
canAdmin={false}
quotedText={selectedQuote}
showCompose={commentOpen}
/>
</div>
</div>
</div>

View File

@@ -16,7 +16,6 @@ function renderBlock(overrides: Record<string, unknown> = {}) {
saveState: 'idle' as const,
canComment: true,
currentUserId: 'user-1',
commentCount: 0,
onTextChange: vi.fn(),
onFocus: vi.fn(),
onDeleteClick: vi.fn(),

View File

@@ -30,34 +30,9 @@ let activeBlockId: string | null = $state(null);
let saveStates = new SvelteMap<string, SaveState>();
let debounceTimers = new SvelteMap<string, ReturnType<typeof setTimeout>>();
let pendingTexts = new SvelteMap<string, string>();
let commentCounts = new SvelteMap<string, number>();
let sortedBlocks = $derived([...blocks].sort((a, b) => a.sortOrder - b.sortOrder));
let hasBlocks = $derived(blocks.length > 0);
async function loadCommentCounts() {
for (const block of blocks) {
try {
const res = await fetch(
`/api/documents/${documentId}/transcription-blocks/${block.id}/comments`
);
if (res.ok) {
const comments = (await res.json()) as Array<{ replies: unknown[] }>;
const total = comments.reduce((s, c) => s + 1 + (c.replies?.length ?? 0), 0);
commentCounts.set(block.id, total);
}
} catch {
// ignore
}
}
}
$effect(() => {
if (blocks.length > 0) {
loadCommentCounts();
}
});
function getSaveState(blockId: string): SaveState {
return saveStates.get(blockId) ?? 'idle';
}
@@ -191,7 +166,6 @@ $effect(() => {
saveState={getSaveState(block.id)}
canComment={canComment}
currentUserId={currentUserId}
commentCount={commentCounts.get(block.id) ?? 0}
onTextChange={(text) => handleTextChange(block.id, text)}
onFocus={() => handleFocus(block.id)}
onDeleteClick={() => handleDelete(block.id)}