Logo-Kacheln, Logo-Infozeile und Detailseite zeigen keinen Ersatz („von Anonym“, alter Anzeigename) mehr, der gleich auf „von @name“
wechselt: Solange die Abfrage für den Hochlader läuft, ist die Zeile leer und behält ihre Höhe (U+200B vor dem leeren Inhalt in
logos.css und community.css); danach steht der Name, ohne Profil oder bei einem Fehler der Ersatz. Schon bekannte Hochlader zeigen
ihre Zeile sofort, ein gemeldeter Name beendet das Warten. Die Infozeile lässt dabei Zeile und Trenner weg („<Name> · ♥ <Zahl>“),
LogoInfoHost bekommt byline(logo) statt names().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Logo-Kacheln, Logo-Infozeile und die Detailseite einer Community-Karte zeigen den Benutzernamen des Kontos (Hilfsfunktion byline: Profil,
sonst alter Anzeigename, sonst „Anonym“). Die Namen kommen je geladener Seite in einer Abfrage nach, ein Fehler dabei bleibt ohne Fehlertext,
ein eigenes Umbenennen aktualisiert die eigenen Einträge sofort.
Die Felder „Anzeigename“ in den Dialogen „Logo hochladen“ und „Veröffentlichen“ fallen weg, ebenso account/display-name.ts und der
localStorage-Schlüssel; der Client schickt displayName: ''. Vor dem Hochladen und Veröffentlichen verlangt requireUsername() einen Namen
(„Abbrechen“: es passiert nichts); antwortet der Dienst mit 403 usernameRequired, öffnet sich der Namensdialog, danach ist ein neuer Versuch möglich.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Blendete ein Admin das gewählte Logo im Picker aus (oder ein), forgetLogo leerte zwar den Zwischenspeicher, aber der Editor behielt seine schon
geladenen Logo-Bilder: Vorschau und Miniaturen zeigten weiter den alten Stand, bis sich Logo, Details oder Marke änderten.
- logo-picker.ts: neuer Rückruf `onLogoChanged(id)` (Typ LogoPickerHandlers). Der Picker ruft ihn, wenn die Infozeile ein Logo aus- oder eingeblendet hat
(nach patchRow, die Zeile ist dann schon aktuell) und nach dem Löschen (nach onSelect(null)).
- editor-page.ts: Ist das gemeldete Logo das gewählte, verwirft der Editor seinen Logo-Zustand samt Sperren (logos, pendingKey, failedKey), blendet den Hinweis
aus und ruft ensureLogos neu: Vorschau und alle vier Miniaturen werden mit dem neuen Stand gezeichnet, der Hinweis „nicht mehr verfügbar“ folgt. Ein
anderes oder kein gewähltes Logo löst nichts aus; ein noch laufender Ladevorgang wird überholt (Token).
- editor-page.ts, followDownload: Stand die Karte nach einem Ladefehler ohne Logo da (`failed`), kehrte der Download früh zurück, obwohl er die Logos
geladen hatte: das PNG hatte das Logo, die Vorschau nicht. Jetzt übernimmt die Vorschau es (Hinweis passend, failedKey leer).
- editor-page.ts, doSave: forgetLogo(config.logo) vor dem Laden der Bilder, wie Download und Veröffentlichen; ein inzwischen ausgeblendetes Logo kommt nicht
mehr ins Vorschaubild der gespeicherten Karte.
- editor-page.ts: Beim Ladefehler für eine neue Auswahl blieb der Hinweis „Das gewählte Logo ist nicht mehr verfügbar.“ der früheren Auswahl neben dem neuen
Fehler stehen; die Logos der früheren Auswahl und ihr Hinweis fallen jetzt sofort weg (andere Hinweise bleiben).
- Tests: Picker (Rückruf nach Aus-/Einblenden und Löschen mit Reihenfolge, nicht bei Fehlern, Herz, Melden, nach dem Aufräumen) und Editor (Aus- und Einblenden,
anderes oder kein Logo, überholter Ladevorgang, nach Ladefehler, mit dem echten Zwischenspeicher; Download-Übernahme, Speichern, alter Hinweis neben Fehler).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- logo-picker.ts: Verschwindet „Mehr laden“ oder „Nochmal versuchen“, während es den Fokus hat, geht der Fokus weiter statt auf der Seite verloren zu
gehen: an den Knopf, der seinen Platz einnimmt („Nochmal versuchen“ nach einem Fehler beim Nachladen), sonst an die erste Kachel, die der Ladevorgang
angehängt hat, sonst an die Überschrift „Logo unten rechts“ (jetzt tabindex −1). Ein gesperrter Knopf verliert den Fokus, darum bleibt „Mehr laden“
während des Ladens bedienbar, solange es ihn hat (ein zweiter Druck ist wirkungslos, load prüft es); ohne Fokus bleibt es gesperrt wie bisher.
Wer den Fokus woanders hat, bekommt ihn nicht weggenommen.
- logo-picker.ts: das Raster hat role="list" (list-style: none nimmt dem <ul> sonst die Listensemantik) und kein eigenes aria-labelledby mehr; der
Name steht an der Gruppe. Das lokale `const select` in createTile verdeckte die Funktion select() und heißt jetzt selectButton.
- logo-picker.ts, removeLogo: War das gelöschte Logo der Cursor und steht kein früheres mehr in der Liste, wurde der Cursor verworfen und „Mehr laden“
verschwand samt aller weiteren Seiten. Jetzt beginnt die Ansicht wieder bei Seite 1 (load('reset')).
- Tests: Fokus in allen Fällen (letzte Seite, weitere Seite, Fehler, Retry bei leerer und gefüllter Liste, Fokus woanders, nur schon bekannte Logos,
nach dem Aufräumen), role/aria-labelledby/tabindex, Cursor ohne Vorgänger (auch in der Admin-Ansicht „Gemeldet“) und die Fälle ohne Neuladen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schlussreview F5. Geht die Antwort einer Löschanfrage verloren und der Nutzer klickt noch einmal auf „Löschen“, antwortet der Dienst mit
404 `logoGone` (das Logo ist ja schon weg). Die Infozeile zeigte dann „Dieses Logo ist nicht (mehr) verfügbar.“ als Fehler, die Kachel
blieb stehen.
- Dieser Fehler (ApiError mit Status 404 und Schlüssel `logoGone`) gilt wie ein gelungenes Löschen: forgetLogo, die Kachel verschwindet,
eine Auswahl wird aufgehoben (onSelect(null)), kein Fehlertext – wie bei „Zurückziehen“ einer schon zurückgezogenen Karte.
- Jeder andere Fehler bleibt einer, auch ein 404 mit anderem oder ohne Schlüssel (etwa ein Dienst, der die Anfrage nicht kennt).
- Tests in logo-info.test.ts (Hochlader, Admin, Seite verlassen, Fehler, die Fehler bleiben) und im Picker mit Raster und Auswahl.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schlussreview F2. Hat jemand das Logo gelöscht oder ausgeblendet, hinter dem „Mehr laden“ ansetzt (der Cursor), antwortet Appwrite mit
400 `general_cursor_not_found`. „Nochmal versuchen“ wiederholte dann denselben Cursor und scheiterte immer wieder.
- Dieser Fehlertyp beim Nachladen löst jetzt `load('reset')` aus: die erste Seite der aktuellen Ansicht (gleiche Sortierung, gleicher Filter)
wird neu geladen, die Kachel des gewählten Logos bleibt stehen. Kein Fehlertext, kein „Nochmal versuchen“ für den toten Cursor.
- Jeder andere Fehler beim Nachladen und jeder Fehler beim Laden der ersten Seite bleibt wie bisher (Meldung und „Nochmal versuchen“);
die erste Seite hat keinen Cursor, ein Neuladen im Kreis ist ausgeschlossen.
- Tests mit einem Fehler {code: 400, type: 'general_cursor_not_found'}: Neuladen von Seite 1 mit Anfragefolge, Ansicht „Gemeldet“ bleibt,
gewählte Kachel bleibt, Neuladen scheitert selbst, anderer Fehlertyp, Fehlertyp beim ersten Laden.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Schlussreview F1. Scheiterte das Laden der Bilder (Netz, Server), bricht draw() ab, solange logos.key nicht zur Auswahl passt: Vorschau
und Miniaturen blieben leer, und ein erneuter Klick auf dieselbe Kachel änderte nichts, weil failedKey dem Schlüssel entsprach.
- Nach einem echten Ladefehler lädt der Editor einmal die Marke allein (loadCardAssets mit logo: null) und zeichnet die Karte damit ohne
Logo (`failed`); scheitert auch das, fehlt die Marke ebenfalls. LOGO_ERROR bleibt stehen, die Auswahl auch. Ein anderes Logo wird nie mit
den Bildern der gescheiterten Auswahl gezeichnet (der Schlüssel entscheidet wie bisher).
- Der Picker meldet jeden Klick, auch auf das schon gewählte Logo: ist es das Logo, dessen Laden scheiterte, hebt der Editor die Sperre
(failedKey) auf und versucht es noch einmal. Ein geladenes Logo wird dabei nicht neu geladen, ein Fehlschlag wiederholt sich nicht im Kreis.
- Tests: Karte ohne Logo nach dem Fehler (Vorschau und vier Miniaturen), Wiederholung per Klick (Erfolg und erneuter Fehlschlag, kein Loop),
Marke lädt auch nicht, anderes Logo nach dem Fehler, Klick auf geladenes Logo lädt nichts neu; Picker meldet den Klick auf die gewählte
Kachel. Zwei bestehende Tests angepasst: „nicht gezeichnet nach Fehler“ gilt nicht mehr, und die Zahl der loadCardAssets-Aufrufe zählt
jetzt den zusätzlichen Lauf für die Marke nicht mehr mit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 9: die Infozeile zum gewählten Logo unter dem Raster (Spec § 3 und § 6).
- logos/logo-info.ts (neu): „<Name> · von <Anzeigename> · ♥ <Zahl>“ und „Melden“ (auch für Gäste; ein ausgeblendetes Logo lässt
sich nicht melden). Der Hochlader sieht „Löschen“ mit Rückfrage (Titel mit Namen, Folgen im Text), Admins „<n> Meldungen“ mit den
Gründen als Text (listLogoReports, einmal je Logo und Stand), „Ausblenden“/„Einblenden“ und „Löschen“. Gelöscht: deleteLogo,
forgetLogo, Kachel weg, onSelect(null); ein-/ausgeblendet: setLogoVisibility, forgetLogo (ein Null-Bild bleibt nicht im Zwischen-
speicher), die Zeile des Pickers wird fortgeschrieben (Einblenden setzt reportCount auf 0). Gewähltes Logo nicht auffindbar: „Das
gewählte Logo ist nicht mehr verfügbar.“ (ein Netzfehler von getLogo sagt nichts). Zugleich die Meldezeile (role="alert") für Fehler
von Herz, Hochladen und diesen Aktionen; ein Wechsel der Auswahl räumt sie ab. Immer nur eine Aktion zugleich; die Rechte werden
nach der Rückfrage noch einmal geprüft; der Aufbau steht einmal da, update() ändert nur Texte und Sichtbarkeit (Fokus bleibt).
- logos/logo-picker.ts: hängt die Infozeile als Letztes unter das Raster (info.el). Herz- und Upload-Fehler gehen in die Infozeile,
der Statusbereich des Pickers bleibt den Ladefehlern der Liste vorbehalten (ein Klick auf ein Herz löscht ihren Text nicht mehr).
Aus dem Review von Task 8: requireLogin, das wirft, zeigt den Grund statt einer unbehandelten Ablehnung; select() nach dispose()
ist wirkungslos. Löschen entfernt Kachel, Zeile, Herz und Eintrag der Liste, setzt den Cursor von „Mehr laden“ auf das Logo davor
(Appwrite lehnt einen Cursor auf eine gelöschte Zeile ab), hebt die Auswahl über onSelect(null) auf und holt den Fokus nach
„Kein Logo“, wenn er auf „Löschen“ lag. LogoPickerDeps erweitert um reportLogo, deleteLogo, setLogoVisibility, listLogoReports,
confirm und reportDialog.
- community/report-dialog.ts: subject 'card' (Standard, unverändert) oder 'logo': Überschrift „Logo melden“, Einleitung „dieses
Logo“, vier Gründe ohne „Echte Kartendaten“, Duplikat-Dank „Danke, du hast dieses Logo schon gemeldet.“. Der ganze Dialog geht
durch t()/msg(); Fehler des Dienstes über apiErrorText.
- logos/logos.css: das Herz sitzt in der Textzeile unter der Bildfläche (nicht mehr auf dem Logo, folgt dem Theme), die Kachel füllt
die Zelle (height: 100%), damit „Kein Logo“ so hoch ist wie sein Nachbar; Stile der Infozeile.
- editor/editor-page.ts: Aus dem Review von Task 8: der Ladefehler der Logos verschwindet, sobald ein Logo danach lädt, aber nur
der, den der Logo-Zustand selbst ins Fehlerfeld geschrieben hat; jeder andere Text im Feld bleibt.
- i18n/en.ts: englische Texte zu allen neuen Beschriftungen und zum Melden-Dialog.
- Tests: logo-info.test.ts (neu), logo-picker.test.ts (Infozeile, Löschen, Ein-/Ausblenden, Fehler, Cursor, Fokus), report-dialog.test.ts
(Logo und Englisch), editor-page.test.ts (Fehlerfeld). Vitest 52 Dateien, 1764 Tests grün, tsc und Build sauber.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 8: der Bereich „Logo unten rechts“ in der Optionsspalte des Editors (Spec § 3 und § 5).
- logos/logo-picker.ts (neu): createLogoPicker baut Kopf (Überschrift, Plakette „Community“, „+ Hochladen“, Satz zur Community), den
Umschalter „Beliebt“/„Neu“ (Admins zusätzlich „Gemeldet“/„Ausgeblendet“, je eine Ansicht mit sort und filter) und das Raster:
erste Kachel „Kein Logo“, je Logo eine Kachel mit Bild, Name, „von <Anzeigename>“ bzw. „von Anonym“ und einem eigenen Herz-Knopf
neben dem Auswahlknopf. „Mehr laden“ hängt die nächste Seite an (Duplikate nur einmal), Leer-Text und Ladefehler mit „Nochmal
versuchen“ (wiederholt genau den gescheiterten Schritt); nur die jüngste Antwort einer Ansicht zählt. Die Auswahl gehört dem
Editor: ein Klick meldet onSelect, markiert wird über select(); ein Logo außerhalb der Liste wird nach dem Laden der ersten Seite
per getLogo geholt und als zweite Kachel angeheftet (steht es in der Liste, gibt es keine Anfrage). selected() liefert die Zeile
für die Infozeile in Task 9. Herzen: optimistisch mit Rücksprung und Fehlertext (role="alert"); solange eine Anfrage für ein
Logo läuft, bleiben weitere Klicks auf sein Herz wirkungslos; Gäste öffnen erst den Login (abgebrochen: nichts passiert, kein
Fehlertext); die Herzen einer Seite kommen mit genau deren IDs, beim Anmelden für alle gezeigten Logos, beim Abmelden aus; eine
späte Antwort überschreibt kein inzwischen selbst geschaltetes Herz. „Hochladen“ meldet Gäste zuerst an, öffnet den Dialog (mit
Signal, das beim Verlassen der Seite schließt), setzt das neue Logo als erste Kachel, ruft rememberLogo und onSelect(id).
- logos/logo-image.ts (neu): das PNG einer Kachel laden, auf die Pixelgrenze prüfen (MAX_LOGO_PIXELS, so wie checkGalleryImage die
Galerie-Bilder prüft; darüber, nicht lesbar oder Ladefehler: neutraler Platzhalter statt Absturz) und zeigen: mehrfarbig als <img>,
einfarbig als weiße Maske, immer auf dem dunklen Kartengrund. Die Object-URL gibt die zurückgegebene Funktion frei; eine Datei, die
erst danach eintrifft, wird nicht mehr angezeigt.
- logos/logo-asset.ts: MAX_LOGO_PIXELS wird exportiert (eine Quelle für Renderer und Kacheln).
- logos/logos.css: Kopf, Umschalter, Raster (ab 1024 px zwei Spalten, sonst auto-fill ab 140 px), Kacheln mit Bildfläche auf #1B2738,
Herz (gefüllt, wenn gedrückt), Leer- und Fehlerzeilen; Bild und Maske teilen sich die Regeln mit der Dialog-Vorschau.
- editor/editor-page.ts: der Picker sitzt in options.logoSlot, die Wahl setzt config.logo, sync ruft picker.select(config.logo), das
Verlassen der Seite ruft dispose. Übernommen aus dem Review von Task 5: failedKey blockiert ein Logo nicht mehr für immer, eine
andere Wahl (Logo, Details, Marke) hebt die Sperre auf; derselbe Schlüssel wird weiter nicht im Kreis neu versucht.
- editor/dom.ts: Symbole heart und plus. i18n/en.ts: englische Texte zu allen neuen Beschriftungen.
- Tests: logo-picker.test.ts (Aufbau, Sortierung, Mehr laden, Auswahl und angeheftetes Logo, Herzen mit Rennen und Login, Leer und
Ladefehler, Hochladen, Kachelbilder, dispose, Englisch), logo-image.test.ts, editor-page.test.ts (Verdrahtung, Regressionstest zu
failedKey). Vitest 51 Dateien, 1666 Tests grün, tsc und Build sauber.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>