Drei Wege, die über ein Neuladen führten
**In „Fortsetzen" startet ein Tipp.** Dort steht ein Titel, *weil* man ihn angefangen hat, und die Stelle steht daneben — der Umweg über die Detailseite stellte eine Frage, die schon beantwortet war. Überall sonst bleibt es beim Weg auf die Seite: wer nachsehen will, wie viele Staffeln eine Serie hat, soll nicht den Film bekommen. **Ein Haken nimmt die Kachel mit.** In „Fortsetzen" und „Als Nächstes" steht, was offen ist. Eine abgehakte Folge ist nicht mehr offen — sie mit einem Haken stehen zu lassen sah aus, als hätte das Abhaken nicht gewirkt. Dasselbe für „Aus Fortsetzen entfernen": in der Reihe selbst heisst entfernen genau das. **Und ein getauschtes Bild erreicht den Aufmacher.** Wer auf der Startseite ein Plakat wechselt, sieht denselben Titel gleich darüber in voller Breite — dort stand bis zum nächsten Neuladen das alte. Die Kachel frischt sich selbst auf; der Aufmacher steht ganz woanders und erfuhr nichts davon. Jetzt meldet der Bilderdialog es der ganzen Seite, und wer es angeht, hört zu. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
adca700c4a
commit
2c535e6f47
@@ -16,6 +16,19 @@ type Bildart = 'poster' | 'backdrop' | 'logo';
|
|||||||
* Fenster sähe man dasselbe zweimal im Monat. */
|
* Fenster sähe man dasselbe zweimal im Monat. */
|
||||||
const AUFMACHER_HOECHSTENS = 5;
|
const AUFMACHER_HOECHSTENS = 5;
|
||||||
|
|
||||||
|
/** Sagt der ganzen Seite, dass ein Bild gewechselt hat.
|
||||||
|
*
|
||||||
|
* **Weil der Rückruf nur den erreicht, der den Dialog geöffnet hat.** Wer
|
||||||
|
* auf der Startseite das Plakat einer Kachel tauscht, ändert damit auch den
|
||||||
|
* Aufmacher — und der steht ganz woanders und weiss von nichts. Bisher
|
||||||
|
* musste man die Seite neu laden, um das neue Bild zu sehen.
|
||||||
|
*
|
||||||
|
* Ein Ereignis am Dokument statt eines durchgereichten Rückrufs: der
|
||||||
|
* Aufmacher hört zu, ohne dass die Kachel ihn kennen müsste. */
|
||||||
|
export function bildgeaendertMelden(art: 'movies' | 'series', id: string): void {
|
||||||
|
document.dispatchEvent(new CustomEvent('flaro:bildgeaendert', { detail: { art, id } }));
|
||||||
|
}
|
||||||
|
|
||||||
/** Was jede Bildart ist — und in welcher Form sie hochgeladen wird.
|
/** Was jede Bildart ist — und in welcher Form sie hochgeladen wird.
|
||||||
*
|
*
|
||||||
* **`zuschnitt: null` beim Schriftzug, und das ist kein Versehen.** Ein
|
* **`zuschnitt: null` beim Schriftzug, und das ist kein Versehen.** Ein
|
||||||
@@ -212,6 +225,7 @@ export function bilderflaeche(
|
|||||||
// Kachel zeigte danach das alte Bild weiter — bis man die ganze
|
// Kachel zeigte danach das alte Bild weiter — bis man die ganze
|
||||||
// Oberfläche neu lud.
|
// Oberfläche neu lud.
|
||||||
beiAenderung?.();
|
beiAenderung?.();
|
||||||
|
bildgeaendertMelden(art, id);
|
||||||
hinweisZeigen(`${name} gesetzt.`);
|
hinweisZeigen(`${name} gesetzt.`);
|
||||||
await laden();
|
await laden();
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
@@ -232,6 +246,7 @@ export function bilderflaeche(
|
|||||||
try {
|
try {
|
||||||
await bildFreigeben(art, id, bildart);
|
await bildFreigeben(art, id, bildart);
|
||||||
beiAenderung?.();
|
beiAenderung?.();
|
||||||
|
bildgeaendertMelden(art, id);
|
||||||
hinweisZeigen('Kommt beim nächsten Auffrischen wieder aus der Quelle.');
|
hinweisZeigen('Kommt beim nächsten Auffrischen wieder aus der Quelle.');
|
||||||
await laden();
|
await laden();
|
||||||
} catch (fehler) {
|
} catch (fehler) {
|
||||||
@@ -345,6 +360,7 @@ export function bilderflaeche(
|
|||||||
async function speichern(neu: string[]): Promise<void> {
|
async function speichern(neu: string[]): Promise<void> {
|
||||||
await aufmacherSetzen(art, id, neu);
|
await aufmacherSetzen(art, id, neu);
|
||||||
beiAenderung?.();
|
beiAenderung?.();
|
||||||
|
bildgeaendertMelden(art, id);
|
||||||
await laden();
|
await laden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -412,6 +428,7 @@ export function bilderflaeche(
|
|||||||
try {
|
try {
|
||||||
await bildSetzen(art, id, bildart, kandidat!.url);
|
await bildSetzen(art, id, bildart, kandidat!.url);
|
||||||
beiAenderung?.();
|
beiAenderung?.();
|
||||||
|
bildgeaendertMelden(art, id);
|
||||||
await laden();
|
await laden();
|
||||||
}
|
}
|
||||||
catch (fehler) {
|
catch (fehler) {
|
||||||
|
|||||||
+18
-9
@@ -22,7 +22,14 @@ export type Kachel = {
|
|||||||
*
|
*
|
||||||
* **Bisher nur für „Als Nächstes".** Dort heisst Weglegen etwas anderes
|
* **Bisher nur für „Als Nächstes".** Dort heisst Weglegen etwas anderes
|
||||||
* als in „Fortsetzen": nicht diese Folge, sondern diese Serie. */
|
* als in „Fortsetzen": nicht diese Folge, sondern diese Serie. */
|
||||||
reihe?: 'naechste';
|
reihe?: 'naechste' | 'fortsetzen';
|
||||||
|
/** Was ein Tipp auslöst, wenn es nicht die Detailseite sein soll.
|
||||||
|
*
|
||||||
|
* **Nur in „Fortsetzen".** Dort ist die Absicht eindeutig: der Titel steht
|
||||||
|
* in der Reihe, *weil* man ihn angefangen hat, und die Stelle steht
|
||||||
|
* daneben. Überall sonst führt der Tipp auf die Seite — wer nur nachsehen
|
||||||
|
* will, wie viele Staffeln eine Serie hat, soll nicht den Film bekommen. */
|
||||||
|
starten?: () => void;
|
||||||
art: 'filme' | 'serien';
|
art: 'filme' | 'serien';
|
||||||
/** Die obere, fette Zeile. Bei einer Folge die Serie. */
|
/** Die obere, fette Zeile. Bei einer Folge die Serie. */
|
||||||
titel: string;
|
titel: string;
|
||||||
@@ -107,7 +114,7 @@ export function kachel(k: Kachel, oeffnen: (art: 'filme' | 'serien', id: string)
|
|||||||
// muss — sie liest sie vom angeklickten Element ab.
|
// muss — sie liest sie vom angeklickten Element ab.
|
||||||
knopf.dataset.id = k.id;
|
knopf.dataset.id = k.id;
|
||||||
knopf.dataset.art = k.art;
|
knopf.dataset.art = k.art;
|
||||||
knopf.onclick = () => oeffnen(k.art, k.id);
|
knopf.onclick = () => (k.starten ? k.starten() : oeffnen(k.art, k.id));
|
||||||
|
|
||||||
// **Das Kontextmenü an jeder Kachel, überall.** Gesehen, Favorit und
|
// **Das Kontextmenü an jeder Kachel, überall.** Gesehen, Favorit und
|
||||||
// Weglegen gab es nur auf der Detailseite — in einer Übersicht mit zwanzig
|
// Weglegen gab es nur auf der Detailseite — in einer Übersicht mit zwanzig
|
||||||
@@ -297,14 +304,14 @@ function kachelpunkte(
|
|||||||
// weiss nur der Server.
|
// weiss nur der Server.
|
||||||
k.stand = await gesehen(k.standId ?? k.id, !istGesehen);
|
k.stand = await gesehen(k.standId ?? k.id, !istGesehen);
|
||||||
|
|
||||||
// **In „Als Nächstes" ist ein Haken ein Abschied.**
|
// **In „Fortsetzen" und „Als Nächstes" ist ein Haken ein Abschied.**
|
||||||
//
|
//
|
||||||
// Die Reihe zeigt, was dran ist. Eine abgehakte Folge ist nicht mehr
|
// Beide Reihen zeigen, was offen ist. Eine abgehakte Folge ist nicht
|
||||||
// dran — sie mit einem Haken stehen zu lassen sah aus, als hätte das
|
// mehr offen — sie mit einem Haken stehen zu lassen sah aus, als
|
||||||
// Abhaken nicht gewirkt. Gemessen: der Server lieferte beim nächsten
|
// hätte das Abhaken nicht gewirkt. Der Server lieferte beim nächsten
|
||||||
// Laden längst die richtige Folge, nur sah man das nie, weil die
|
// Laden längst das Richtige; nur sah man das nie, weil die Reihe
|
||||||
// Reihe nicht neu geladen wurde.
|
// nicht neu geladen wurde.
|
||||||
if (k.reihe === 'naechste' && !istGesehen) {
|
if (k.reihe && !istGesehen) {
|
||||||
knopf.remove();
|
knopf.remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -335,6 +342,8 @@ function kachelpunkte(
|
|||||||
text: 'Aus Fortsetzen entfernen',
|
text: 'Aus Fortsetzen entfernen',
|
||||||
tun: async () => {
|
tun: async () => {
|
||||||
await weglegen(k.standId ?? k.id);
|
await weglegen(k.standId ?? k.id);
|
||||||
|
// In der Reihe selbst heisst „entfernen" genau das.
|
||||||
|
if (k.reihe === 'fortsetzen') { knopf.remove(); return; }
|
||||||
if (k.stand) k.stand.dismissed = true;
|
if (k.stand) k.stand.dismissed = true;
|
||||||
knopf.querySelector('.fortschritt')?.remove();
|
knopf.querySelector('.fortschritt')?.remove();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
inhalt, weiterschauen, naechsteFolgen, empfehlungen, saisonal,
|
inhalt, weiterschauen, naechsteFolgen, empfehlungen, saisonal,
|
||||||
type Bibliothek,
|
type Bibliothek, type Angefangen,
|
||||||
} from '../api';
|
} from '../api';
|
||||||
import { leer, fehlerzeile, meldung } from '../util';
|
import { leer, fehlerzeile, meldung } from '../util';
|
||||||
import { kachel, alsKachel, angefangenAlsKachel, reihe } from '../card';
|
import { kachel, alsKachel, angefangenAlsKachel, reihe } from '../card';
|
||||||
@@ -77,6 +77,21 @@ export function startseite(
|
|||||||
});
|
});
|
||||||
vorschlag.items.forEach(e => dazu(alsHero(e, 'filme')));
|
vorschlag.items.forEach(e => dazu(alsHero(e, 'filme')));
|
||||||
|
|
||||||
|
/** Was ein Tipp in „Fortsetzen" tut. */
|
||||||
|
function fortsetzenStarten(e: Angefangen): void {
|
||||||
|
// Ohne Datei gibt es nichts zu starten — dann führt der Tipp
|
||||||
|
// dorthin, wo man wählen kann. Dieselbe Regel wie im Aufmacher.
|
||||||
|
if (!e.fileId) { oeffnen(e.seriesId ? 'serien' : 'filme', e.seriesId ?? e.id); return; }
|
||||||
|
spieler({
|
||||||
|
dateiId: e.fileId,
|
||||||
|
titelId: e.id,
|
||||||
|
name: e.subTitle ?? e.title,
|
||||||
|
ab: e.state.positionSeconds,
|
||||||
|
laenge: e.durationSeconds ?? null,
|
||||||
|
danach: () => void aufbauen(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const aufmacher = hero(heroTitel,
|
const aufmacher = hero(heroTitel,
|
||||||
(art, id) => oeffnen(art, id),
|
(art, id) => oeffnen(art, id),
|
||||||
e => {
|
e => {
|
||||||
@@ -95,9 +110,24 @@ export function startseite(
|
|||||||
signal);
|
signal);
|
||||||
if (aufmacher) wurzel.appendChild(aufmacher);
|
if (aufmacher) wurzel.appendChild(aufmacher);
|
||||||
|
|
||||||
|
// **Ein getauschtes Bild gehört sofort in den Aufmacher.**
|
||||||
|
//
|
||||||
|
// Wer auf dieser Seite das Plakat oder den Hintergrund eines Titels
|
||||||
|
// wechselt, sieht ihn gleich darüber in voller Breite — und dort stand
|
||||||
|
// bis zum nächsten Neuladen das alte. Die Kachel frischt sich selbst
|
||||||
|
// auf; der Aufmacher hat davon nichts erfahren, weil er ganz woanders
|
||||||
|
// steht. Siehe `bildgeaendertMelden`.
|
||||||
|
document.addEventListener('flaro:bildgeaendert', () => void aufbauen(), { signal });
|
||||||
|
|
||||||
if (weiter.items.length) {
|
if (weiter.items.length) {
|
||||||
|
// **Hier startet ein Tipp.** In „Fortsetzen" steht ein Titel, *weil*
|
||||||
|
// man ihn angefangen hat, und die Stelle steht daneben — den Umweg
|
||||||
|
// über die Detailseite zu nehmen hiesse, eine Frage zu stellen, die
|
||||||
|
// schon beantwortet ist.
|
||||||
wurzel.appendChild(reihe('Fortsetzen',
|
wurzel.appendChild(reihe('Fortsetzen',
|
||||||
weiter.items.map(e => kachel(angefangenAlsKachel(e), oeffnen))));
|
weiter.items.map(e => kachel(
|
||||||
|
{ ...angefangenAlsKachel(e, 'fortsetzen'), starten: () => fortsetzenStarten(e) },
|
||||||
|
oeffnen))));
|
||||||
}
|
}
|
||||||
if (naechste.items.length) {
|
if (naechste.items.length) {
|
||||||
wurzel.appendChild(reihe('Nächste Folge',
|
wurzel.appendChild(reihe('Nächste Folge',
|
||||||
|
|||||||
Reference in New Issue
Block a user