cards-native/PLAN.md
Till JS cf1160b270 v0.4.0 — Phase β-3 Editor
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>
2026-05-13 00:24:43 +02:00

6.3 KiB

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.

Pflicht-Check für β-2: Endurance-Test auf realem Gerät (200+ Karten mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.

SOT: ../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md. Dieses File ist die App-lokale Status-Spur, das Greenfield-Doc hat die ganze Architektur-Begründung.

Aktueller Stand

β-0 — Setup (2026-05-12, Tag v0.1.0)

  • Repo-Skelett unter git.mana.how/till/cards-native
  • project.yml mit Bundle-ID ev.mana.cards, ManaSwiftCore via path: ../mana-swift-core
  • AppConfig als ManaAppConfig-Provider:
    • Auth: https://auth.mana.how
    • API: https://cardecky-api.mana.how
    • Keychain-Service: ev.mana.cards
  • CardsTheme.swift mit forest-Werten (lokal nachgebaut aus mana/packages/themes/src/variants/forest.css)
  • LoginView (Email/PW gegen mana-auth)
  • 3 Unit-Tests (AppConfig)

β-3 — Editor (2026-05-13, Tag v0.4.0)

  • DeckCreateBody, DeckUpdateBody, CardCreateBody, CardUpdateBody Encodable-Structs (snake_case via CodingKeys, nil-Felder werden weggelassen)
  • CardFieldsBuilder mit Type-spezifischen Pflicht-Feld-Konstruktoren
  • CardsAPI: createDeck/updateDeck/deleteDeck + createCard/updateCard/deleteCard
  • DeckEditorView für Create + Edit in einer View (mode-switch), Color-Picker mit 8-Preset-Palette aus forest-Theme, Category-Picker (11 Kategorien mit deutschen Labels), Visibility-Segmented-Control
  • CardEditorView mit Type-Picker (basic, basic-reverse, cloze, typing, multiple-choice) und dynamischen Feldern je Typ. Cloze-View zeigt Live-Cluster-Count und Hint-Syntax-Hinweis. image-occlusion und audio-front zeigen β-4-Placeholder
  • DeckDetailView mit 4 Action-Buttons (Lernen, Karte hinzufügen, Bearbeiten, Löschen), Confirmation-Dialog für Delete
  • DeckListView: "+"-Button im Toolbar (Leading), Sheet für Create
  • 7 zusätzliche Encoding-Tests (24 Unit-Tests total)

β-2 — Study-Loop (2026-05-13, Tag v0.3.0)

  • Card, Review, DueReview Codable-DTOs, CardType-Enum (alle 7 Typen)
  • Rating-Enum: again | hard | good | easy mit deutschen Labels
  • Cloze-Helpers (extractClusterIds, subIndexCount, clusterId, renderPrompt, renderAnswer, hint) — 1:1-Port aus cards/packages/cards-domain/src/cloze.ts
  • CardsAPI.dueReviews(deckId:), CardsAPI.gradeReview(...) mit ISO8601-Encoder
  • PendingGrade SwiftData-Model + GradeQueue für Offline-Submit (FIFO-Drain, originaler reviewedAt-Timestamp bleibt erhalten)
  • StudySession als @Observable State-Machine (loading/studying/finished/failed)
  • CardRenderer: basic, basic-reverse (sub-index-abhängig), cloze client-rendered. image-occlusion/audio-front/typing/multiple-choice zeigen Placeholder (β-3/β-4)
  • RatingBar mit Haptic-Feedback (medium für again/hard/good, heavy für easy, soft beim Flip)
  • StudySessionView vollbild aus DeckListView per NavigationLink
  • 9 zusätzliche Tests (Cloze 8x, Review/DueReview-Decoding 3x)

β-1 — Decks lesen (2026-05-13, Tag v0.2.0)

  • Deck-Codable-DTO mit snake_case-CodingKeys, plus DeckCategory, DeckVisibility, FsrsSettings
  • ISO8601-Date-Decoder mit Fractional-Seconds-Toleranz
  • CardsAPI.listDecks(), cardCount(deckId:), dueCount(deckId:)
  • CachedDeck als SwiftData-Model mit lastFetchedAt (Offline-Read)
  • DeckListStore orchestriert API + Cache, paralleles Counts-Fetching via TaskGroup
  • DeckListView mit Pull-to-Refresh, Card/Due-Counts, deck.color-Streifen, Inbox-Banner für Marketplace-Forks
  • AccountView mit Sign-out-Button
  • iOS-Simulator-Build + Tests grün (6 Unit-Tests, 1 UI-Test)

Phasen (Detail in Greenfield-Plan)

Phase Status Inhalt
β-0 2026-05-12 Setup, Login, API-Probe
β-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
β-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)

Aus Greenfield-Plan-Sektion "Phase β-4":

  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/, LRU 200 MB)
  6. CardEditorView um image-occlusion + audio-front erweitern

Erfolgskriterium: Karten mit Bildern und Audio aus Web-erstellten Decks funktionieren in Native. Image-Occlusion in beide Richtungen (Native↔Web) sichtbar.

Verschoben auf β-3-Extension oder später

  • Anki-Import (.apkg-Parser): Web parsed client-side und ruft POST /cards pro Karte. Native bräuchte eigenen Swift-Parser für Anki-Pakete (Plist/sqlite/.apkg) — eigener Brocken, nicht blockierend für andere Phasen.
  • Card-Edit (PATCH /cards/:id): Card-Create reicht für Web-Parität in v1, Edit kann später nachgereicht werden.
  • Distractor-Vorschau für Multiple-Choice-Editor: Server liefert Distractors zur Lernzeit (/decks/:deckId/distractors), Editor zeigt sie nicht — Web macht das auch nicht.

Pflicht-Tests für β-2 (vor β-3-Start)

  • Endurance-Test auf realem Gerät: 200+ Karten lernen, Flugmodus zwischendurch — alle Grades landen am Server nach Reconnect.
  • Cross-Check mit Web: Karte gegrade in Native → Web zeigt identischen Review-State nach Reload.

Cross-Refs

  • ../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md — Greenfield-Plan SOT
  • ../mana/docs/MANA_SWIFT.md — Plattform-SOT
  • ../cards/CLAUDE.md — Cards-Repo
  • ../cards/STATUS.md — Web-Phasenstand (Referenz)
  • ../mana-swift-core/CLAUDE.md — ManaCore-Konventionen
  • CLAUDE.md — Repo-Konventionen