feat(comments): hide every comment mention when COMMENTS_ENABLED=false

The kill-switch previously left comment UI/text visible in several places.
Sweep the whole surface so a comments-off instance shows no trace:

Frontend (main app):
- VirtualFeed grid tile: gate the comment button/count on $commentsEnabled
  (was ungated — the only feed surface still showing it).
- admin stats: hide the "Kommentare" count card.
- UploadSheet "Uploads geschlossen" notice, host ban-modal description, and
  host/admin unban confirmations: drop the "…und kommentieren" wording.
- export page: drop "Kommentaren" from the keepsake description.

Keepsake export (had no concept of the flag):
- export.rs: thread comments_enabled into the exported data (ViewerEvent),
  wired through spawn_export_jobs/recover_exports and their call sites
  (host.rs, main.rs).
- export-viewer: gate comment counts (list + grid) and the lightbox comments
  section; older exports without the field default to enabled (?? true).

Backend still 403s comment writes when disabled (unchanged) — this is the UI
half so stale clients and archives match.

Verified on the running stack (COMMENTS_ENABLED=false): /event reports
comments_enabled=false, a regenerated keepsake embeds "comments_enabled": false
with no comment UI, and the uploads-closed notice renders "…ansehen und liken."

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-07-19 18:26:59 +02:00
parent e1ca9d192f
commit 3fb1b5d80d
11 changed files with 133 additions and 78 deletions

View File

@@ -8,7 +8,12 @@
import Modal from '$lib/components/Modal.svelte';
import IconButton from '$lib/components/IconButton.svelte';
import { PRESETS, DEFAULT_SEED, buildPaletteCss, type ThemeConfig } from '$lib/theme/palette';
import { previewTheme, PALETTE_CACHE_KEY, loadEventConfig } from '$lib/event-config-store';
import {
previewTheme,
PALETTE_CACHE_KEY,
loadEventConfig,
commentsEnabled
} from '$lib/event-config-store';
import { onDestroy } from 'svelte';
interface StatsDto {
@@ -644,12 +649,14 @@
</p>
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">Uploads</p>
</div>
<div class="card p-4 text-center">
<p class="text-3xl font-bold text-gray-900 dark:text-gray-100">
{stats.comment_count}
</p>
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">Kommentare</p>
</div>
{#if $commentsEnabled}
<div class="card p-4 text-center">
<p class="text-3xl font-bold text-gray-900 dark:text-gray-100">
{stats.comment_count}
</p>
<p class="mt-0.5 text-xs text-gray-500 dark:text-gray-400">Kommentare</p>
</div>
{/if}
<div class="card p-4 text-center">
<p class="text-3xl font-bold text-gray-900 dark:text-gray-100">
{diskPct(stats)} %
@@ -1053,7 +1060,7 @@
onclick={() =>
(confirmAction = {
title: 'Sperre aufheben?',
message: `${user.display_name} kann danach wieder hochladen, liken und kommentieren.`,
message: `${user.display_name} kann danach wieder hochladen${$commentsEnabled ? ', liken und kommentieren' : ' und liken'}.`,
confirmLabel: 'Entsperren',
tone: 'default',
run: () => unban(user)

View File

@@ -7,6 +7,7 @@
import { toastError } from '$lib/toast-store';
import { focusTrap } from '$lib/actions/focus-trap';
import IconButton from '$lib/components/IconButton.svelte';
import { commentsEnabled } from '$lib/event-config-store';
interface JobStatus {
status: 'locked' | 'pending' | 'running' | 'done' | 'failed';
@@ -266,7 +267,8 @@
<div class="min-w-0">
<h2 class="section-title">HTML-Viewer</h2>
<p class="mt-0.5 text-sm text-gray-500 dark:text-gray-400">
Schöne Offline-Galerie mit Filterung, Kommentaren und Likes — kein Internet nötig.
Schöne Offline-Galerie mit Filterung{$commentsEnabled ? ', Kommentaren' : ''} und Likes
— kein Internet nötig.
</p>
<p
class="mt-1 text-xs {status.html.status === 'done'

View File

@@ -9,6 +9,7 @@
import ConfirmSheet from '$lib/components/ConfirmSheet.svelte';
import Modal from '$lib/components/Modal.svelte';
import IconButton from '$lib/components/IconButton.svelte';
import { commentsEnabled } from '$lib/event-config-store';
interface UserSummary {
id: string;
@@ -448,9 +449,10 @@
Benutzer sperren
</h2>
<p class="mb-4 text-sm text-gray-600 dark:text-gray-400">
<strong>{banTarget.display_name}</strong> wird gesperrt: alle Uploads verschwinden aus Galerie,
Diashow und Export, und Hochladen, Liken und Kommentieren werden blockiert. Der Lesezugriff (Feed
ansehen, Keepsake herunterladen) bleibt bestehen. Rückgängig machbar über „Entsperren“.
<strong>{banTarget.display_name}</strong> wird gesperrt: alle Uploads verschwinden aus
Galerie, Diashow und Export, und Hochladen, Liken{$commentsEnabled ? ' und Kommentieren' : ''} werden
blockiert. Der Lesezugriff (Feed ansehen, Keepsake herunterladen) bleibt bestehen. Rückgängig machbar
über „Entsperren“.
</p>
<div class="flex gap-2">
<button onclick={() => (banTarget = null)} class="btn btn-secondary flex-1">
@@ -823,7 +825,7 @@
onclick={() =>
(confirmAction = {
title: 'Sperre aufheben?',
message: `${user.display_name} kann danach wieder hochladen, liken und kommentieren.`,
message: `${user.display_name} kann danach wieder hochladen${$commentsEnabled ? ', liken und kommentieren' : ' und liken'}.`,
confirmLabel: 'Entsperren',
tone: 'default',
run: () => unban(user)