fix(card): fehlendes Logo bricht nur ab, wenn die Vorlage es zeichnet; Download aus „Meine Karten“ meldet es
Entscheidung des Controllers zu Task 5: Ein fehlendes Community-Logo ist beim Rendern einer gespeicherten Karte nur dann ein Problem, wenn die Vorlage es zeichnet (layoutFor(template).logo). Bei „Nur Bild“ wird ein Logo nie gezeichnet, dort fehlt nichts. Der Editor-Hinweis (Auswahlzustand) und der Download im Editor bleiben unverändert. - community/publish.ts: neue gemeinsame Prüfung assertLogoAvailable(config, assets); sie wirft LOGO_MISSING_PUBLISH, wenn assets.logoMissing gilt und die Vorlage das Logo zeichnet (minimal, classic, signature). renderForGallery nutzt sie: bei einer zeichnenden Vorlage Abbruch vor dem Rendern (nichts hochgeladen), bei „Nur Bild“ wird normal gerendert und veröffentlicht. - pages/cards-page.ts: der Download einer gespeicherten Karte ruft dieselbe Prüfung. Statt stillschweigend ohne Logo herunterzuladen, zeigt die Kachel den Text LOGO_MISSING_PUBLISH über den vorhandenen Fehlermechanismus (run() und failureText() schreiben in .card-msg), übersetzt mit t(); es wird nichts exportiert oder gespeichert. Bei „Nur Bild“ läuft der Download normal. - Tests: publish.test.ts (classic/minimal/signature mit fehlendem Logo brechen ab, „Nur Bild“ veröffentlicht normal, Wahrheitstabelle für assertLogoAvailable) und cards-page.test.ts (Download mit fehlendem Logo: Meldung, kein Download; „Nur Bild“ und vorhandenes Logo: Download wie sonst; zweiter Versuch; Englisch). Vitest 45 Dateien, 1338 Tests grün, tsc und Build sauber. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0be5abd954
commit
8205f7c37f
4 files changed
+147
-14
No files matched your search
@@ -4,9 +4,10 @@
|
||||
import { ID, Permission, Role } from 'appwrite';
|
||||
import { IDS, storage } from '../account/appwrite';
|
||||
import { cardsService, requireUserId, toUploadFile, type SavedCard } from '../account/cards';
|
||||
import { CARD_W, PREVIEW_QUALITY, PREVIEW_WIDTH } from '../card/geometry';
|
||||
import type { CardConfig } from '../card/config';
|
||||
import { CARD_W, PREVIEW_QUALITY, PREVIEW_WIDTH, layoutFor } from '../card/geometry';
|
||||
import { clampCrop } from '../card/crop';
|
||||
import { exportCard, loadCardAssets } from '../card/render';
|
||||
import { exportCard, loadCardAssets, type LoadedAssets } from '../card/render';
|
||||
import { decodeImage } from '../editor/upload';
|
||||
import { msg } from '../i18n/i18n';
|
||||
import { isDefinitiveFailure, publishCard, type PublishInput } from './api';
|
||||
@@ -15,7 +16,7 @@ import { isDefinitiveFailure, publishCard, type PublishInput } from './api';
|
||||
export const PNG_MAX_BYTES = 5_242_880;
|
||||
export const TOO_LARGE = 'Das Kartenbild ist zu groß für die Galerie (max. 5 MB).';
|
||||
export const NOT_RENDERED = 'Das Kartenbild konnte nicht erzeugt werden.';
|
||||
/** Die Karte wählt ein Logo, das gelöscht oder ausgeblendet wurde: veröffentlicht wird sie nicht ohne dieses Logo. */
|
||||
/** Die Karte wählt ein Logo, das gelöscht oder ausgeblendet wurde: ohne dieses Logo wird sie weder veröffentlicht noch heruntergeladen. */
|
||||
export const LOGO_MISSING_PUBLISH = msg(
|
||||
'Das Logo dieser Karte ist nicht mehr verfügbar. Öffne die Karte im Editor und wähle ein anderes.',
|
||||
);
|
||||
@@ -52,12 +53,22 @@ export function normalizeTags(input: string): string[] {
|
||||
return tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft nach dem Laden der Bilder einer gespeicherten Karte, ob ihr beim Rendern etwas fehlt (Veröffentlichen und Herunterladen
|
||||
* aus „Meine Karten“): Gibt es das gewählte Community-Logo nicht mehr (gelöscht, ausgeblendet) und zeichnet die Vorlage es, wirft
|
||||
* das LOGO_MISSING_PUBLISH. So wird nie eine andere Karte veröffentlicht oder heruntergeladen, als der Nutzer sie gestaltet hat.
|
||||
* Bei „Nur Bild“ wird ein Logo nie gezeichnet: dort fehlt nichts, und es wird ganz normal gerendert.
|
||||
*/
|
||||
export function assertLogoAvailable(config: CardConfig, assets: LoadedAssets): void {
|
||||
if (assets.logoMissing && layoutFor(config.template).logo) throw new Error(LOGO_MISSING_PUBLISH);
|
||||
}
|
||||
|
||||
export async function renderForGallery(card: SavedCard, imageBlob: Blob): Promise<{ png: Blob; preview: Blob }> {
|
||||
const image = await decodeImage(imageBlob);
|
||||
const config = { ...card.config, crop: clampCrop(image, card.config.crop) };
|
||||
const assets = await loadCardAssets(config, image);
|
||||
// Ohne das gewählte Logo würde eine andere Karte veröffentlicht, als der Nutzer sie gestaltet hat: lieber abbrechen.
|
||||
if (assets.logoMissing) throw new Error(LOGO_MISSING_PUBLISH);
|
||||
// Lieber abbrechen, als eine Karte ohne ihr Logo zu veröffentlichen.
|
||||
assertLogoAvailable(config, assets);
|
||||
const png = await exportCard(config, assets, { width: CARD_W, type: 'image/png' });
|
||||
const preview = await exportCard(config, assets, { width: PREVIEW_WIDTH, type: 'image/webp', quality: PREVIEW_QUALITY });
|
||||
return { png, preview };
|
||||
|
||||
Reference in new issue
Block a user