cards-native/PLAN.md
Till JS 3b861af3fb v0.3.0 — Phase β-2 Study-Loop
Voller Lern-Flow mit Web-Parität: fällige Karten via /reviews/due
laden, flip + rate (4 Buttons + Haptic), Grades via Offline-Queue
ans Server-FSRS schicken.

- Card/Review/DueReview DTOs mit snake_case + camelCase-deckId-
  Sonderfall im embedded card-Subobjekt
- CardType-Enum (alle 7 Typen), Rating-Enum mit deutschen Labels
- Cloze-Helper 1:1-Port aus cards-domain (extractClusterIds,
  subIndexCount, clusterId, renderPrompt/Answer, hint)
- CardsAPI.dueReviews(deckId:) + gradeReview(cardId,subIndex,rating,reviewedAt)
- PendingGrade SwiftData-Model + GradeQueue (FIFO-Drain, originaler
  Timestamp bleibt, bei Netzfehler in Queue, Retry beim nächsten Drain)
- StudySession @Observable State-Machine
- CardRenderer für basic, basic-reverse, cloze; Placeholder für
  image-occlusion/audio-front/typing/multiple-choice (β-3/β-4)
- RatingBar mit UIImpactFeedbackGenerator (medium/heavy)
- StudySessionView per NavigationLink aus DeckListView
- 9 neue Tests (Cloze: 8, Review-Decoding: 3), insgesamt 17 grün

Server-authoritative FSRS bleibt — kein ts-fsrs-Port.
Endurance-Test auf realem Gerät steht aus (siehe PLAN.md).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 00:16:11 +02:00

4.6 KiB

Plan — cards-native (SwiftUI Universal)

Stand: 2026-05-13 — Phasen β-0 + β-1 + β-2 abgeschlossen. Repo auf Forgejo, Login funktioniert, Deck-Liste mit Cache + Pull-to-Refresh, voller Study-Loop mit Flip/Rating/Haptic + Offline-Queue für Grades (PendingGrade SwiftData). Cloze client- rendered (1:1-Port aus cards-domain). 17 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)

β-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 Card-/Deck-Editor (basic, cloze, typing, multiple-choice)
β-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 β-3 (Editor)

Aus Greenfield-Plan-Sektion "Phase β-3 — Card-/Deck-Editor":

  1. DeckCreateView: Form für Name, Description, Color (Picker), Category-Picker, Visibility, FSRS-Settings (Sheet)
  2. CardEditorView per Type (basic, cloze, typing, multiple-choice): Two-Text-Fields oder Cloze-Syntax-Highlighting
  3. POST/PATCH/DELETE /api/v1/cards und /api/v1/decks
  4. Anki-Import als Datei-Picker → /api/v1/decks/import

Erfolgskriterium: Karte in Native erstellt, in Web sichtbar; Karte in Web erstellt, in Native sichtbar (Pull-to-Refresh).

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