Phase A: acht weitere QR-Typen
E-Mail, SMS, WhatsApp, WLAN, Standort, vCard, Zahlung und App-Link sind umgesetzt. Damit sind 9 der 15 Typen nutzbar. Erweiterungen am Typ-Vertrag, die dafuer noetig waren: - supportsStatic: nicht jeder Typ kann statisch. Beim App-Link steht das Ziel erst beim Scannen fest, also gibt es ihn nur dynamisch. - RedirectContext: die Weiterleitung reicht den User-Agent durch, damit der App-Link iOS, Android und alles Uebrige unterscheiden kann. - assertDynamicPossible(): supportsDynamic ist eine Eigenschaft des Typs, aber nicht jede Eingabe taugt dafuer. Ein GiroCode ist kein Web-Ziel, obwohl der Typ 'Zahlung' als Zahlungslink sehr wohl dynamisch sein kann. Ohne diese Probe liess sich ein Code speichern, der erst beim Scannen aufgefallen waere - also nach dem Drucken. Greift beim Anlegen und beim Bearbeiten. Sorgfalt bei den Formaten, gesammelt in src/lib/qr/encoding.ts: - WLAN maskiert ; , : \\ und setzt rein hexadezimale Werte in Anfuehrungszeichen, sonst deuten Geraete sie als Hexzahl. - vCard 3.0 mit CRLF, Maskierung und Faltung nach 75 Oktetten, oktettweise gezaehlt, damit kein mehrbytiges Zeichen zerrissen wird. - GiroCode nach EPC069-12 mit fester Feldreihenfolge, IBAN-Pruefsumme nach Modulo 97 und der 331-Byte-Grenze. - Rufnummern werden nach E.164 normalisiert, '(0)' faellt weg. - Standort nimmt Koordinaten auch aus einem Google-Maps- oder Apple-Link an. Formular-Bausteine (Select, Textarea, Checkbox, FieldRow, FieldSet) fuer die mehrfeldrigen Typen ergaenzt. Geprueft: 225 Pruefungen, davon 80 neu - Dekodierung je Typ aus dem fertigen PNG, Validierung, Betriebsarten, geraeteabhaengige Weiterleitung und die Formulare im Browser.
This commit is contained in:
+37
-5
@@ -7,6 +7,7 @@ import { designSchema } from "@/lib/qr/design";
|
||||
import {
|
||||
QR_TYPE_IDS,
|
||||
QrRequestError,
|
||||
QrTypeError,
|
||||
type QrTypeModule,
|
||||
} from "@/lib/qr/type-module";
|
||||
import { shortUrl } from "@/lib/env";
|
||||
@@ -40,6 +41,35 @@ export type QrRequest = z.infer<typeof qrRequestSchema>;
|
||||
// dass ein Ringschluss zwischen den beiden Modulen entsteht.
|
||||
export { QrRequestError };
|
||||
|
||||
/**
|
||||
* Prüft, ob sich aus diesen Daten überhaupt ein Weiterleitungsziel bilden
|
||||
* lässt — und zwar, indem es einmal gebildet wird.
|
||||
*
|
||||
* `supportsDynamic` ist eine Eigenschaft des Typs, aber nicht jede Eingabe
|
||||
* eines dynamikfähigen Typs taugt dafür: ein GiroCode etwa ist kein Web-Ziel,
|
||||
* obwohl der Typ „Zahlung“ in seiner Link-Variante sehr wohl dynamisch sein
|
||||
* kann. Ohne diese Probe entstünde ein gespeicherter Code, der erst beim
|
||||
* Scannen auffällt — also genau dann, wenn er schon gedruckt ist.
|
||||
*/
|
||||
export function assertDynamicPossible(
|
||||
qrType: QrTypeModule,
|
||||
data: Record<string, unknown>,
|
||||
): void {
|
||||
if (!qrType.supportsDynamic) {
|
||||
throw new QrRequestError(
|
||||
`Der QR-Typ „${qrType.title}“ unterstützt keine dynamischen Codes.`,
|
||||
);
|
||||
}
|
||||
try {
|
||||
qrType.redirectTarget(data, {});
|
||||
} catch (error) {
|
||||
if (error instanceof QrTypeError) {
|
||||
throw new QrRequestError(error.message);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export type ResolvedQrRequest = {
|
||||
qrType: QrTypeModule;
|
||||
data: Record<string, unknown>;
|
||||
@@ -62,11 +92,7 @@ export async function resolveQrRequest(
|
||||
}
|
||||
|
||||
if (request.mode === "dynamic") {
|
||||
if (!qrType.supportsDynamic) {
|
||||
throw new QrRequestError(
|
||||
`Der QR-Typ „${qrType.title}“ unterstützt keine dynamischen Codes.`,
|
||||
);
|
||||
}
|
||||
assertDynamicPossible(qrType, validated.data);
|
||||
const slug = request.slug;
|
||||
if (slug !== undefined && !isValidSlug(slug)) {
|
||||
throw new QrRequestError("Ungültige Kurz-URL.");
|
||||
@@ -78,6 +104,12 @@ export async function resolveQrRequest(
|
||||
};
|
||||
}
|
||||
|
||||
if (!qrType.supportsStatic) {
|
||||
throw new QrRequestError(
|
||||
`Der QR-Typ „${qrType.title}“ funktioniert nur als dynamischer Code.`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
qrType,
|
||||
data: validated.data,
|
||||
|
||||
Reference in New Issue
Block a user