feat: Medien im Fenster ansehen, und eine Auffrischung, die nichts wegzieht

ANSEHEN OHNE NEUEN TAB. Klick auf eine Kachel oeffnet den Betrachter: Bilder,
Videos, Ton und PDF direkt, alles andere mit ehrlichem Hinweis und
Herunterladen-Knopf -- ein Betrachter, der bei einer .zip ein schwarzes Feld
zeigt, sieht aus wie ein kaputter Betrachter. Pfeiltasten blaettern, Escape
schliesst; Adresse kopieren, neuer Tab und Loeschen sitzen in der Kopfzeile.

Gezeigt wird IMMER die Vollfassung, nie die Vorschau: 320 Pixel reichen fuer
eine Kachel, aber nicht dafuer, ein Bild zu beurteilen -- und genau dazu klickt
man darauf.

Damit musste die Auswahl umziehen: der Klick auf die Kachel oeffnet jetzt, das
Kaestchen oben links waehlt aus. Es erscheint beim Darueberfahren und bleibt
sichtbar, solange etwas gewaehlt ist.

AUTOMATISCH AUFFRISCHEN, aber nicht stumpf. Ein billiger Fuehler
(/api/dash/stand: drei Zahlen, GEMESSEN 6 ms je Abfrage ueber TLS und Proxy)
wird alle fuenf Sekunden gefragt; erst wenn er sich aendert, wird richtig
nachgeladen. Ein Tab im Hintergrund fragt gar nicht.

Die dritte Zahl ist kein Zierrat: nach einem LOESCHEN gehen Anzahl und
neuester Zeitstempel auf die alten Werte zurueck -- nur die Ereignis-ID zaehlt
weiter. Ohne sie bliebe eine geloeschte Datei in der Galerie stehen.
Nachgemessen.

UND ES ZIEHT NICHTS WEG: wer etwas ausgewaehlt hat, ein Bild offen hat oder
geblaettert ist, bekommt keinen Neuaufbau unter den Haenden, sondern einen
Knopf "Neues da -- laden". Eine Liste, die sich beim Klicken selbst neu
sortiert, ist der Grund, warum Leute Auto-Refresh abschalten. Der Schalter
merkt sich seinen Zustand.

Kein SSE, und das mit Absicht: dafuer braeuchte NPM zusaetzlich
`proxy_buffering off` -- ein weiterer Handgriff im Proxy, der vergessen werden
kann und dann zu einer Verbindung fuehrt, die scheinbar haengt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 18:49:02 +02:00
co-authored by Claude Opus 5
parent dffec7714c
commit 1c5bf20eb0
6 changed files with 468 additions and 9 deletions
+37 -1
View File
@@ -16,6 +16,7 @@ import { api, type EventKind, type EventsSeite } from '../api'
import { useStore } from '../store'
import { bytes, zeit } from '../format'
import { Karte, Knopf, Leer } from '../components/Bausteine'
import { useAuffrischen } from '../auffrischen'
const SEITENGROESSEN = [25, 50, 100, 200] as const
@@ -61,6 +62,12 @@ export function Verlauf() {
void laden()
}, [laden])
// Im Verlauf ist das Mitlesen der eigentliche Zweck: waehrend ein
// Serienlauf laeuft, sieht man hier zu. Blockiert wird nur, wenn man
// geblaettert hat -- eine Seite drei, die unter den Haenden zu Seite eins
// wird, ist aergerlich.
const frisch = useAuffrischen({ laden: () => void laden(), blockiert: seite > 0 })
const items = daten?.items ?? []
const seiten = Math.max(1, Math.ceil((daten?.total ?? 0) / proSeite))
@@ -96,7 +103,36 @@ export function Verlauf() {
/>
))}
<span className="ml-auto text-sm text-schrift-leise">
{frisch.wartet && (
<Knopf
art="haupt"
className="ml-auto"
onClick={frisch.jetztLaden}
kind={
<>
<RefreshCw size={14} />
Neues da laden
</>
}
/>
)}
<label
className={`flex cursor-pointer items-center gap-1.5 text-xs text-schrift-leise ${
frisch.wartet ? '' : 'ml-auto'
}`}
title="Alle fünf Sekunden nachsehen, ob etwas dazugekommen ist"
>
<input
type="checkbox"
checked={frisch.an}
onChange={(e) => frisch.setAn(e.target.checked)}
className="accent-akzent"
/>
automatisch
</label>
<span className="text-sm text-schrift-leise">
{laedt ? (
<Loader2 size={15} className="animate-spin" />
) : (