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>
The frontend had no JS/TS linter — only svelte-check. Add flat-config ESLint (typescript-eslint
+ eslint-plugin-svelte) and Prettier (tabs/single-quote, matching the existing style).
Rules encode "catch bugs, not enforce taste":
- svelte/require-each-key KEPT — it is the exact bug class as the feed mis-tap fix. Fixed every
flagged block: keyed activeFilters, filteredUsers, stagedFiles (by previewUrl), captionTags,
admin tabs/jobs/users, the export-viewer suggestions/filters/comments, and the static skeleton
loops.
- svelte/prefer-svelte-reactivity KEPT — inline-disabled only the verified-safe sites (a local
freq Map in a $derived.by, throwaway URLSearchParams query builders), with a reason each.
- svelte/no-navigation-without-resolve OFF — wants resolve() around every goto()/href; taste, not
a bug, and pure churn.
- svelte/no-unused-svelte-ignore OFF — those comments are consumed by svelte-check, which ESLint
can't see, so it wrongly calls them unused; removing them would reintroduce a11y warnings.
- no-explicit-any OFF for *.test.ts only (partial fixtures legitimately use any).
Real code fixes beyond keys: removed a dead jobLabel(), an unused ViewerComment import and unused
catch binding, an unused scroll-lock arg, and replaced an empty interface with a type alias.
Then `prettier --write` (54 files). Formatting only. Verified: eslint clean, svelte-check 0 errors,
vitest 46 passed, vite build succeeds.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Post-commit review follow-ups for the batch-3 feed work.
Frontend — VirtualFeed: the guarded setOptions keyed only on (count, scrollMargin),
so a rotation (or the first-paint 0->real container width) changed colWidth / card
heights without invalidating the cached measurements, leaving getTotalSize and the
scrollbar stale until each row scrolled back through the window. Track appliedWidth
and call virtualizer.measure() on a width delta so heights re-estimate at the new
width (rendered rows re-measure immediately via their ResizeObserver). Covers list +
grid and the first-paint 120px-estimate case.
Backend — social.rs: the fresh like/comment count SELECT used `.await?`, so a
transient DB failure would 500 the request after the like/comment had already
committed. Make the count + broadcast best-effort (if let Ok { ... }); the mutation
succeeds regardless and the next event / pull-to-refresh reconciles the count.
Docs — FOLLOWUPS: record the review findings left as-is (grid-prepend tile reflow,
filtered-grid auto-load which is pre-existing, comment-delete stale count, and the
last-write-wins count ordering note).
Verified: svelte-check 0 errors, cargo build clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>