v0.5.0 — Phase β-4 Media + Advanced Card-Types
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>
This commit is contained in:
parent
cf1160b270
commit
80eb3708b4
12 changed files with 923 additions and 44 deletions
72
PLAN.md
72
PLAN.md
|
|
@ -1,9 +1,10 @@
|
|||
# Plan — cards-native (SwiftUI Universal)
|
||||
|
||||
**Stand: 2026-05-13 — Phasen β-0 + β-1 + β-2 + β-3 abgeschlossen.**
|
||||
Login, Deck-Liste mit Cache, Study-Loop mit Offline-Grade-Queue,
|
||||
voller Editor-Flow (Deck Create/Edit/Delete + Card Create für 5
|
||||
Types). 24 Unit-Tests + 1 UI-Test grün.
|
||||
**Stand: 2026-05-13 — Phasen β-0 bis β-4 abgeschlossen.**
|
||||
Alle 7 Card-Types werden gerendert und können erstellt werden,
|
||||
inklusive image-occlusion (Touch-Drag-Mask-Editor) und audio-front
|
||||
(File-Picker + AVAudioPlayer). MediaCache mit LRU 200 MB.
|
||||
30 Unit-Tests + 1 UI-Test grün.
|
||||
|
||||
Pflicht-Check für β-2: Endurance-Test auf realem Gerät (200+ Karten
|
||||
mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
||||
|
|
@ -27,6 +28,30 @@ mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
|||
- `LoginView` (Email/PW gegen mana-auth)
|
||||
- 3 Unit-Tests (AppConfig)
|
||||
|
||||
✅ **β-4 — Media + Advanced Card-Types (2026-05-13, Tag `v0.5.0`)**
|
||||
- `MediaUploadResponse` DTO + `MediaKind`-Enum
|
||||
- `MaskRegion` Codable mit 0..1-Coordinates, `MaskRegions.parse/encode`-
|
||||
Helpers (1:1-Port aus `cards-domain/image-occlusion.ts` — Sortierung
|
||||
nach ID lexikographisch)
|
||||
- `CardFieldsBuilder.imageOcclusion`, `.audioFront` mit korrekter
|
||||
`mask_regions`-Serialisierung als stringified JSON-Array
|
||||
- `CardsAPI.uploadMedia(data, filename, mimeType)` mit Multipart
|
||||
(25 MiB max), `.fetchMedia(id)` für streamed bytes
|
||||
- `MediaCache` actor mit LRU 200 MB (sortiert nach `contentModificationDate`)
|
||||
- `mediaCache`-Environment-Key, im App-Entrypoint instantiiert
|
||||
- `RemoteImage` View — authentifiziertes Image-Loading mit ProgressView
|
||||
+ Failure-State
|
||||
- `AudioPlayerButton` — AVAudioPlayer-Wrapper mit Play/Pause-Toggle,
|
||||
AVAudioSession-Setup für iOS
|
||||
- `CardRenderer.imageOcclusionView`: AsyncImage + opake Maske über aktiver
|
||||
Region (Frontside), Label-Reveal auf Backside
|
||||
- `CardRenderer.audioFrontView`: AudioPlayerButton + back-Text auf Flip
|
||||
- `MaskEditorView`: Touch-Drag-to-Create-Rectangle, Liste mit Label-Edit
|
||||
+ Delete, 0..1-Normalisierung beim Commit
|
||||
- `CardEditorView` erweitert: PhotosPicker für Image, fileImporter für
|
||||
Audio, Magic-Byte-MIME-Detection (JPEG/PNG/GIF/WebP)
|
||||
- 6 neue Tests für MaskRegions-Parse/Encode + Field-Builder (30 Total)
|
||||
|
||||
✅ **β-3 — Editor (2026-05-13, Tag `v0.4.0`)**
|
||||
- `DeckCreateBody`, `DeckUpdateBody`, `CardCreateBody`, `CardUpdateBody`
|
||||
Encodable-Structs (snake_case via `CodingKeys`, nil-Felder werden
|
||||
|
|
@ -86,28 +111,37 @@ mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
|||
| β-1 | ✅ 2026-05-13 | Decks lesen, SwiftData-Cache, Pull-to-Refresh |
|
||||
| β-2 | ✅ 2026-05-13 | Study-Loop, Offline-Grade-Queue (Endurance-Test offen) |
|
||||
| β-3 | ✅ 2026-05-13 | Editor: Deck-CRUD + Card-Create (5 Types); Anki-Import auf β-3-ext verschoben |
|
||||
| β-4 | — | Media, image-occlusion (PencilKit), audio-front |
|
||||
| β-4 | ✅ 2026-05-13 | Media-Upload, image-occlusion (Touch-Mask-Editor), audio-front (AVAudioPlayer) |
|
||||
| β-5 | — | Marketplace, Universal-Links |
|
||||
| β-6 | — | Native-Polish (Widgets, Notifications, Share-Extension) |
|
||||
| β-7 | — | App-Store-Submission |
|
||||
|
||||
## Nächste Schritte für β-4 (Media + Advanced Card-Types)
|
||||
## Nächste Schritte für β-5 (Marketplace)
|
||||
|
||||
Aus Greenfield-Plan-Sektion "Phase β-4":
|
||||
Aus Greenfield-Plan-Sektion "Phase β-5":
|
||||
|
||||
1. Media-Upload via `POST /api/v1/media` (Multipart, 25 MiB max,
|
||||
MinIO-Backend), PHPickerViewController für Foto-Auswahl
|
||||
2. `audio-front`-Cards: AVAudioPlayer für Wiedergabe (Pattern aus
|
||||
memoro-native)
|
||||
3. `image-occlusion`-Renderer: SVG-Mask-Overlay über AsyncImage,
|
||||
Tap auf Mask → Reveal
|
||||
4. iPad-PencilKit-Editor für Image-Occlusion-Masks
|
||||
5. `MediaCache` im FileManager (Caches/cards-media/<id>, LRU 200 MB)
|
||||
6. `CardEditorView` um image-occlusion + audio-front erweitern
|
||||
1. `ExploreView`: GET `/api/v1/marketplace/explore` — Featured/Trending
|
||||
2. `BrowseView`: GET `/api/v1/marketplace/decks/browse` mit Filter-Bar
|
||||
3. `PublicDeckView`: GET `/api/v1/marketplace/decks/:slug` — Detail mit
|
||||
Subscribe-Button (= POST `/subscribe/:slug`, Auto-Fork)
|
||||
4. Subscribed-Decks-Liste als zweite Section in `DeckListView`
|
||||
5. **Universal-Links**: `cardecky.mana.how/d/:slug` öffnet App direkt
|
||||
|
||||
**Erfolgskriterium:** Karten mit Bildern und Audio aus Web-erstellten
|
||||
Decks funktionieren in Native. Image-Occlusion in beide Richtungen
|
||||
(Native↔Web) sichtbar.
|
||||
**Erfolgskriterium:** Drei Live-Decks (geografie-welt-top30, english-a2,
|
||||
periodensystem-elemente) sichtbar, subscribebar, lernbar.
|
||||
|
||||
**Vorbedingung:** AASA auf `cardecky.mana.how/.well-known/apple-app-site-association`
|
||||
muss aufgesetzt werden — heute 404. Aufgabe ans Cards-Web-Repo.
|
||||
|
||||
## Notizen aus β-4
|
||||
|
||||
- **PencilKit für Mask-Editor explizit nicht genutzt.** Web macht
|
||||
Image-Occlusion-Masks per Touch-Drag-Rechteck (kein Freihand). Server-
|
||||
Schema (`MaskRegion = {id, x, y, w, h, label}`) erlaubt nur Rechtecke,
|
||||
PencilKit-Strokes wären dafür übersteigert. Wenn später Polygon-Masks
|
||||
oder Freihand-Skizzen dazu kommen, kann PencilKit nachgereicht werden.
|
||||
- **Apple-Pencil-Support** trotzdem grundsätzlich da: SwiftUI's
|
||||
`DragGesture` reagiert auf Pencil-Eingaben genauso wie auf Finger.
|
||||
|
||||
## Verschoben auf β-3-Extension oder später
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue