42 lines
1.4 KiB
Dart
42 lines
1.4 KiB
Dart
/// Fehler des Anzeigenamens.
|
||
enum DisplayNameError {
|
||
empty,
|
||
tooLong,
|
||
|
||
/// Enthält U+200B (Zero Width Space). Die UI zeigt dieselbe Meldung wie für
|
||
/// einen ungültigen Namen (Spec #1 § 5.4), kein eigener Text.
|
||
invalidCharacter,
|
||
}
|
||
|
||
/// Regel für Anzeigenamen (KTO-01 Kriterium 10, KTO-02 Kriterium 1).
|
||
///
|
||
/// Identisch zum Server (`public.trim_ws` + `char_length`): Leerraum am Rand
|
||
/// wird entfernt (Dart `trim()` und `trim_ws` entfernen dieselben Zeichen,
|
||
/// auch NBSP und Tab). Danach 1 bis 30 Unicode-Codepoints, gezählt über
|
||
/// `runes`, nicht über `String.length` (UTF-16). U+200B wird nicht getrimmt,
|
||
/// sondern überall abgelehnt.
|
||
abstract final class DisplayNameRule {
|
||
static const maxLength = 30;
|
||
static const zeroWidthSpace = '';
|
||
|
||
/// Der Wert, der gespeichert und gesendet wird.
|
||
static String normalize(String value) => value.trim();
|
||
|
||
/// Länge in Codepoints nach dem Trim (für den Zähler `n/30`).
|
||
static int length(String value) => normalize(value).runes.length;
|
||
|
||
static DisplayNameError? validate(String value) {
|
||
final name = normalize(value);
|
||
if (name.contains(zeroWidthSpace)) {
|
||
return DisplayNameError.invalidCharacter;
|
||
}
|
||
final count = name.runes.length;
|
||
if (count == 0) {
|
||
return DisplayNameError.empty;
|
||
}
|
||
if (count > maxLength) {
|
||
return DisplayNameError.tooLong;
|
||
}
|
||
return null;
|
||
}
|
||
}
|