feat(study): Typing-Karten + Levenshtein-Match-Logik

CardRenderer für typing ist nicht mehr Placeholder. Web-Vorbild:
TypingView.svelte + cards-domain/typing.ts.

Typing.swift (Sources/Core/Domain/):
- check(input:answer:aliases:) → TypingMatch (correct/close/wrong)
- Normalisierung: trim + lowercase + NFD-Decomp + Combining-Marks
  strippen (Diakritika: ä → a)
- Aliases-Support (Komma-getrennt aus card.fields["aliases"])
- Levenshtein-Threshold max(1, floor(len * 0.2)) → "close"

TypingCardView (Features/Study/):
- TextField mit Auto-Focus 0.15s nach onAppear, Return = Submit
- Submit-Button mit Return-Symbol + primary background
- Nach Submit: Badge (✓ Richtig / ≈ Fast / ✗ Falsch) + User-
  Eingabe in „…" Quotes + Divider + erwartete Antwort
- Haptic-Feedback: heavy bei correct, light bei close/wrong
- Reset on card.id change

TypingTests: 8 Tests für check() — exact, case+whitespace,
NFD-Umlauts, aliases, Levenshtein-close (Berln → Berlin),
empty-input, sowie Levenshtein-Helper-Sanity.

Build 8 → 9. 43 Tests grün (war 35).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-05-13 17:39:39 +02:00
parent 8b1dd5158f
commit 505aa9db19
5 changed files with 323 additions and 4 deletions

View file

@ -55,7 +55,7 @@ targets:
path: Sources/Resources/Info.plist
properties:
CFBundleShortVersionString: "0.1.0"
CFBundleVersion: "8"
CFBundleVersion: "9"
CFBundleDevelopmentRegion: de
CFBundleDisplayName: Cardecky
LSApplicationCategoryType: "public.app-category.education"
@ -111,7 +111,7 @@ targets:
properties:
CFBundleDisplayName: Als Karte speichern
CFBundleShortVersionString: "0.1.0"
CFBundleVersion: "8"
CFBundleVersion: "9"
NSExtension:
NSExtensionPointIdentifier: com.apple.share-services
NSExtensionPrincipalClass: $(PRODUCT_MODULE_NAME).ShareViewController
@ -144,7 +144,7 @@ targets:
properties:
CFBundleDisplayName: Cardecky Widget
CFBundleShortVersionString: "0.1.0"
CFBundleVersion: "8"
CFBundleVersion: "9"
NSExtension:
NSExtensionPointIdentifier: com.apple.widgetkit-extension
entitlements: