ImagePickerLabel als private View-Struct extrahiert. SwiftUIs
PhotosPicker(label:)-Closure ist @Sendable, aber View-Konstruktor-
Calls werden zur Build-Zeit MainActor-isoliert evaluiert — im
Gegensatz zu direktem @State-Zugriff im Closure-Body.
Vorher: pickerLabel als computed property → Warning blieb.
Jetzt: ImagePickerLabel(hasImage: occlusionImage != nil) →
Warning weg, Swift-Build clean.
Archive grün, Build grün, keine Swift-Warnings mehr (nur eine
AppIntents-Framework-Hinweis-Note ohne Auswirkung).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- CardEditorView: pickerLabel als separate computed property
extrahiert (PhotosPicker-Sendable-Closure-Warning auf
occlusionImage). Warning bleibt cosmetisch auf der neuen Property,
Swift-6-Strict-Edge-Case mit SwiftUI ViewBuilders.
- AppIcon.appiconset/Contents.json: mac-Idiom-Slot entfernt
(iOS-only erstmal — macOS-Support kommt mit eigenem Icon-Satz).
Behebt "unassigned child"-Warnings.
- RELEASE_CHECKLIST: /privacy + /help URLs als done markiert
(live deployed in cards-Repo Commit c6488c0).
Archive verifiziert: ARCHIVE SUCCEEDED, drei Provisioning Profiles
(ev.mana.cardecky + .widget + .share) automatisch geholt und gesigned.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Alle 7 Card-Types werden gerendert und können erstellt werden.
image-occlusion mit Touch-Drag-Mask-Editor (kein PencilKit — Server-
Schema erlaubt nur Rechtecke), audio-front mit AVAudioPlayer und
File-Picker.
- MediaUploadResponse-DTO, MaskRegion-Codable mit 0..1-Coordinates
- MaskRegions.parse/encode (1:1-Port aus cards-domain, Sortierung
nach ID lexikographisch)
- CardFieldsBuilder.imageOcclusion mit stringified-JSON-mask_regions
+ audioFront
- CardsAPI.uploadMedia (Multipart, 25 MiB) + fetchMedia (streamed)
- MediaCache actor mit LRU 200 MB (contentModificationDate-Eviction)
- mediaCache Environment-Key
- RemoteImage + AudioPlayerButton SwiftUI-Views
- CardRenderer: imageOcclusion (Mask-Overlay über RemoteImage) +
audioFront (AudioPlayerButton + back-Text auf Flip)
- MaskEditorView: Touch-Drag-Rechteck, Label-Edit, Delete
- CardEditorView erweitert: PhotosPicker für Image, fileImporter
für Audio, Magic-Byte-MIME-Detection
- 6 neue Tests für MaskRegions (30 Total grün)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Voller Editor-Flow für Decks und 5 Card-Types (basic, basic-reverse,
cloze, typing, multiple-choice). image-occlusion + audio-front kommen
mit β-4 (Media). Anki-Import bleibt vorerst aus (Web parsed client-
side, gibt keinen Server-Import-Endpoint zu rufen).
- DeckCreateBody/UpdateBody, CardCreateBody/UpdateBody Encodable
mit snake_case-CodingKeys, nil-Felder werden weggelassen
- CardFieldsBuilder mit Type-spezifischen Pflicht-Feld-Konstruktoren
- CardsAPI: createDeck/updateDeck/deleteDeck +
createCard/updateCard/deleteCard
- DeckEditorView (Create + Edit in einer View): Color-Picker mit
8-Preset-Palette, Category-Picker (11 Kats, deutsche Labels),
Visibility-Segmented-Control
- CardEditorView mit Type-Picker und dynamischen Feldern je Typ.
Cloze-Sektion zeigt Live-Cluster-Count und Hint-Syntax-Hinweis.
image-occlusion/audio-front zeigen β-4-Placeholder
- DeckDetailView mit Action-Buttons (Lernen, Karte hinzufügen,
Bearbeiten, Löschen mit Confirmation)
- DeckListView: "+"-Button im Toolbar (Leading) für Create-Sheet
- 7 neue Encoding-Tests (24 Unit-Tests + 1 UI-Test grün)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>