Zwei Fassungen dürfen gewollt sein, und die Startseite darf nicht warten
**Mehrfachfassungen lassen sich abhaken.** Zwei Dateien an einem Film sind meist zwei Fassungen und völlig in Ordnung. In der Liste standen sie trotzdem für immer: sie rechnet jedes Mal frisch, und es gab keinen Zustand. Wer absichtlich zwei Fassungen hält, konnte die Gruppe nicht loswerden — und unter den gewollten ging das Ungewollte unter. Abgehakt wird eine Dateizahl, kein Zeitpunkt. Ein Zeitstempel müsste gegen `MediaFile.ModifiedAt` verglichen werden, und eine alte Datei, frisch hineinkopiert, behält ihre alte Zeit und käme nie wieder hoch. Die Anzahl ist genau die Frage: kommt eine dritte Fassung dazu, meldet sich die Gruppe von selbst zurück. Gerechnet wird sie auf dem Server — ein Client mit veralteter Liste hakte sonst eine Gruppe mit zwei Dateien ab, die inzwischen drei hat. „Ignorierte zeigen" führt zurück, wie bei den erledigten Meldungen; ohne das wäre das Abhaken unumkehrbar und niemand wüsste, was er weggeklickt hat. **Die Startseite wartete dreimal nacheinander.** Erst die Serverauskunft, dann Konto und Mediatheken, dann erst die Startseite — drei Rundreisen, bevor das erste Bild in Auftrag ging. Liegt eine Sitzung im Speicher, laufen die ersten beiden jetzt zugleich los. Nur dann: ohne Sitzung liefen `/auth/me` und `/libraries` vor der Antwort auf `needsSetup` in ein 401, und die Sitzungsprüfung kann daraufhin abmelden. Gemessen am laufenden Server: `users/me`, `system/info` und `libraries` starten alle bei 37 ms, die Startseitenabfragen folgen bei 73 ms. Vorher lagen drei Runden dazwischen. **Sieben Hintergrundbilder auf einmal waren sechs zu viel.** Jede Folie des Aufmachers bekam sofort ihr `w1280`-Bild; sichtbar ist immer nur eine. Jetzt lädt die sichtbare sofort und der Rest in der Leerlaufzeit — und wer weiterschaltet, bevor das lief, bekommt sein Bild dann. **Die Schrift kam von Google.** `display=swap` rettete den Text, nicht den ersten Aufbau: ein Stylesheet blockiert das Zeichnen, und ein Heimserver ohne Internet oder mit träger Namensauflösung wartete davor. Inter liegt jetzt als zwei Dateien von zusammen sechzig Kilobyte im Projekt, variabel für alle Schnitte, mit `unicode-range` getrennt nach latin und latin-ext. Gemessen: null Anfragen an fonts.googleapis.com. Lizenztext liegt dabei. **Und mein Untertitelvorrat bremste mit.** Er startete sofort beim Hochfahren und las die ganze Mediathek — von derselben Platte, von der die Startseite ihre Bilder holt. Jetzt beginnt er eine Minute später und stellt zurück, solange eine Wiedergabe läuft. Die Datei bleibt dabei vorn in der Reihe; verworfen wird nichts. 678 Tests grün, davon zwei neue. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2809821c9b
commit
1b4784f1db
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
bibliotheken, unzugeordnet, ohneZuordnung, mehrfachfassungen, dateiHerausloesen,
|
||||
bibliotheken, unzugeordnet, ohneZuordnung, mehrfachfassungen, fassungenAbhaken, dateiHerausloesen,
|
||||
type Mehrfachtitel,
|
||||
} from '../../api';
|
||||
import { esc, knopf, meldung, hinweisZeigen } from '../../util';
|
||||
@@ -24,7 +24,21 @@ import { abschnitt } from './teile';
|
||||
export function ohneZuordnungBereich(): HTMLElement {
|
||||
const bereich = document.createElement('section');
|
||||
bereich.classList.add('hidden');
|
||||
bereich.appendChild(abschnitt('Ohne Zuordnung'));
|
||||
/** Ob die abgehakten Mehrfachfassungen gezeigt werden statt der offenen.
|
||||
*
|
||||
* **Ohne diesen Schalter wäre das Abhaken unumkehrbar.** Man klickt eine
|
||||
* Gruppe weg und weiss hinterher nicht mehr, welche es war — dieselbe
|
||||
* Überlegung wie bei den erledigten Meldungen. */
|
||||
let zeigeIgnorierte = false;
|
||||
|
||||
const umschalten = knopf('Ignorierte zeigen', 'btn');
|
||||
umschalten.onclick = () => {
|
||||
zeigeIgnorierte = !zeigeIgnorierte;
|
||||
umschalten.textContent = zeigeIgnorierte ? 'Offene zeigen' : 'Ignorierte zeigen';
|
||||
void laden();
|
||||
};
|
||||
|
||||
bereich.appendChild(abschnitt('Ohne Zuordnung', [umschalten]));
|
||||
|
||||
const liste = document.createElement('div');
|
||||
liste.className = 'einstellungen';
|
||||
@@ -40,7 +54,7 @@ export function ohneZuordnungBereich(): HTMLElement {
|
||||
const ergebnisse = await Promise.all(alle.map(async b => {
|
||||
try {
|
||||
const [offen, mehrfach] = await Promise.all([
|
||||
ohneZuordnung(b.id), mehrfachfassungen(b.id),
|
||||
ohneZuordnung(b.id), mehrfachfassungen(b.id, 300, zeigeIgnorierte),
|
||||
]);
|
||||
return { b, offen, mehrfach };
|
||||
} catch { return null; }
|
||||
@@ -50,11 +64,26 @@ export function ohneZuordnungBereich(): HTMLElement {
|
||||
.filter(e => e !== null)
|
||||
.filter(e => e!.offen.length > 0 || e!.mehrfach.gesamt > 0);
|
||||
|
||||
if (mitFunden.length === 0) { bereich.classList.add('hidden'); return; }
|
||||
// **Solange jemand die Ignorierten ansieht, bleibt der Bereich stehen.**
|
||||
// Sonst verschwände er samt Umschalter in dem Augenblick, in dem die
|
||||
// letzte abgehakte Gruppe zurückgeholt ist — und niemand fände den Weg
|
||||
// zurück auf die offenen.
|
||||
if (mitFunden.length === 0 && !zeigeIgnorierte) {
|
||||
bereich.classList.add('hidden');
|
||||
return;
|
||||
}
|
||||
bereich.classList.remove('hidden');
|
||||
|
||||
liste.innerHTML = '';
|
||||
|
||||
if (mitFunden.length === 0) {
|
||||
const leer = document.createElement('p');
|
||||
leer.className = 'winzig';
|
||||
leer.textContent = 'Hier ist nichts abgehakt.';
|
||||
liste.appendChild(leer);
|
||||
return;
|
||||
}
|
||||
|
||||
mitFunden.forEach(e => {
|
||||
const { b, offen, mehrfach } = e!;
|
||||
|
||||
@@ -76,10 +105,13 @@ export function ohneZuordnungBereich(): HTMLElement {
|
||||
if (mehrfach.gesamt > 0) {
|
||||
liste.appendChild(fassungsgruppe(
|
||||
`${b.name} — ${anzahl(mehrfach.gesamt, 'Titel')} mit mehreren Dateien`,
|
||||
'Meist zwei Fassungen desselben Films — dann ist alles in Ordnung. '
|
||||
+ 'Stehen hier zwei verschiedene Filme, war einer davon nicht mehr zu '
|
||||
+ 'sehen: „Eigener Film" löst ihn wieder heraus.',
|
||||
mehrfach.titel));
|
||||
zeigeIgnorierte
|
||||
? 'Diese Gruppen wurden als geprüft abgehakt. „Wieder zeigen" holt sie zurück.'
|
||||
: 'Meist zwei Fassungen desselben Films — dann ist alles in Ordnung und '
|
||||
+ '„Ignorieren" nimmt die Gruppe aus der Liste. Stehen hier zwei '
|
||||
+ 'verschiedene Filme, war einer davon nicht mehr zu sehen: '
|
||||
+ '„Eigener Film" löst ihn wieder heraus.',
|
||||
mehrfach.titel, b.id));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -90,7 +122,7 @@ export function ohneZuordnungBereich(): HTMLElement {
|
||||
|
||||
/** Dieselbe Gruppe, aber jede Datei einzeln mit einem Weg heraus. */
|
||||
function fassungsgruppe(
|
||||
ueberschrift: string, hinweis: string, titel: Mehrfachtitel[],
|
||||
ueberschrift: string, hinweis: string, titel: Mehrfachtitel[], bibliothek: string,
|
||||
): HTMLElement {
|
||||
const d = document.createElement('div');
|
||||
d.className = 'einstellung';
|
||||
@@ -108,12 +140,35 @@ export function ohneZuordnungBereich(): HTMLElement {
|
||||
const zeile = document.createElement('div');
|
||||
zeile.className = 'fassungstitel';
|
||||
|
||||
const kopfzeile = document.createElement('div');
|
||||
kopfzeile.className = 'fassungsdatei';
|
||||
|
||||
const name = document.createElement('button');
|
||||
name.className = 'ohnezuordnung-zeile';
|
||||
name.innerHTML = `<span class="oz-titel">${esc(t.titel + (t.jahr ? ` (${t.jahr})` : ''))}</span>`;
|
||||
name.onclick = () => bearbeiten(
|
||||
t.art === 'series' ? 'series' : 'movies', t.id, () => void laden());
|
||||
zeile.appendChild(name);
|
||||
|
||||
// **Für die, die absichtlich zwei Fassungen halten.** Die Liste
|
||||
// rechnet jedes Mal frisch; ohne das Abhaken stand eine gewollte
|
||||
// Gruppe hier für immer, und darunter ging das Ungewollte unter.
|
||||
const abhaken = knopf(zeigeIgnorierte ? 'Wieder zeigen' : 'Ignorieren', 'btn klein');
|
||||
abhaken.onclick = async () => {
|
||||
abhaken.disabled = true;
|
||||
try {
|
||||
await fassungenAbhaken(bibliothek, [t.id], !zeigeIgnorierte);
|
||||
hinweisZeigen(zeigeIgnorierte
|
||||
? `„${t.titel}" steht wieder in der Liste.`
|
||||
: `„${t.titel}" gilt als geprüft. Kommt eine Fassung dazu, meldet er sich wieder.`);
|
||||
await laden();
|
||||
} catch (fehler) {
|
||||
hinweisZeigen(meldung(fehler), 'fehler');
|
||||
abhaken.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
kopfzeile.append(name, abhaken);
|
||||
zeile.appendChild(kopfzeile);
|
||||
|
||||
t.dateien.forEach(f => {
|
||||
const d2 = document.createElement('div');
|
||||
|
||||
Reference in New Issue
Block a user