v0.2.0 — Phase β-1 Decks lesen
Deck-Liste mit Web-Parität: alle eigenen Decks aus cardecky-api, Card-/Due-Counts pro Deck (Web-Pattern: separate Calls), Pull-to- Refresh, Offline-Read via SwiftData, Inbox-Banner für Marketplace- Forks. - Deck-Codable-DTO mit snake_case-CodingKeys (DeckCategory, DeckVisibility, FsrsSettings) - ISO8601-Date-Decoder mit Fractional-Seconds-Toleranz - CardsAPI.listDecks() + cardCount() + dueCount() - CachedDeck SwiftData-Model mit lastFetchedAt - DeckListStore (API + Cache, paralleles Counts-Fetching via TaskGroup) - DeckListView mit forest-Theme, deck.color-Streifen, Inbox-Banner - AccountView mit Sign-out - DashboardView durch DeckListView ersetzt - 6 Unit-Tests + 1 UI-Test grün Phasen-Plan: mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
28b20cd934
commit
f664a00b64
12 changed files with 809 additions and 85 deletions
50
PLAN.md
50
PLAN.md
|
|
@ -1,8 +1,9 @@
|
|||
# Plan — cards-native (SwiftUI Universal)
|
||||
|
||||
**Stand: 2026-05-12 — Phase β-0 abgeschlossen.** Repo lebt lokal,
|
||||
ManaCore + ManaTokens als Package-Dependency, Login funktioniert,
|
||||
Cardecky-API-Reachability-Probe.
|
||||
**Stand: 2026-05-13 — Phasen β-0 + β-1 abgeschlossen.** Repo lebt
|
||||
auf Forgejo, Login funktioniert, Deck-Liste mit Card-/Due-Counts +
|
||||
Offline-SwiftData-Cache + Pull-to-Refresh + Inbox-Banner für
|
||||
Marketplace-Forks. 6 Unit-Tests + 1 UI-Test grün.
|
||||
|
||||
> **SOT:** `../mana/docs/playbooks/CARDS_NATIVE_GREENFIELD.md`.
|
||||
> Dieses File ist die App-lokale Status-Spur, das Greenfield-Doc
|
||||
|
|
@ -10,7 +11,7 @@ Cardecky-API-Reachability-Probe.
|
|||
|
||||
## Aktueller Stand
|
||||
|
||||
✅ **β-0 — Setup**
|
||||
✅ **β-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`
|
||||
|
|
@ -21,16 +22,27 @@ Cardecky-API-Reachability-Probe.
|
|||
- `CardsTheme.swift` mit forest-Werten (lokal nachgebaut aus
|
||||
`mana/packages/themes/src/variants/forest.css`)
|
||||
- `LoginView` (Email/PW gegen mana-auth)
|
||||
- `DashboardView` als β-1-Placeholder mit API-Reachability-Indikator
|
||||
- 3 Unit-Tests (AppConfig)
|
||||
- iOS-Simulator-Build grün
|
||||
|
||||
✅ **β-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 | ⏳ | Decks lesen, SwiftData-Cache |
|
||||
| β-1 | ✅ 2026-05-13 | Decks lesen, SwiftData-Cache, Pull-to-Refresh |
|
||||
| β-2 | — | Study-Loop, Offline-Grade-Queue, Endurance-Test |
|
||||
| β-3 | — | Card-/Deck-Editor (basic, cloze, typing, multiple-choice) |
|
||||
| β-4 | — | Media, image-occlusion (PencilKit), audio-front |
|
||||
|
|
@ -38,20 +50,22 @@ Cardecky-API-Reachability-Probe.
|
|||
| β-6 | — | Native-Polish (Widgets, Notifications, Share-Extension) |
|
||||
| β-7 | — | App-Store-Submission |
|
||||
|
||||
## Nächste Schritte für β-1
|
||||
## Nächste Schritte für β-2
|
||||
|
||||
Aus Greenfield-Plan-Sektion "Phase β-1 — Decks lesen":
|
||||
Aus Greenfield-Plan-Sektion "Phase β-2 — Study-Loop":
|
||||
|
||||
1. `Deck`-`Codable`-Struct nach Wire-Format aus
|
||||
`../cards/apps/api/src/routes/decks.ts` + `cards/packages/cards-domain/src/schemas/`
|
||||
2. `CardsAPI.decks() -> [Deck]` mit `GET /api/v1/decks`
|
||||
3. `DeckListView` mit Pull-to-Refresh, Card/Due-Counts
|
||||
4. `CachedDeck` als SwiftData-Model mit `lastFetchedAt`
|
||||
5. Offline-Display bei fehlendem Netz
|
||||
6. Inbox-Banner aus `?forked_from_marketplace=true`-Query
|
||||
1. `Card`-DTO + `Review`-DTO aus `cards/apps/api/src/lib/dto.ts`
|
||||
2. `CardsAPI.dueCards(deckId:)` → fetcht `/reviews/due` + zugehörige
|
||||
`/cards/:id`-Details für die Karten-Inhalte
|
||||
3. `StudySessionView` mit `CardRenderer`-switch (basic + basic-reverse
|
||||
+ cloze; cloze-Rendering kommt vom Server via `renderClozePrompt`)
|
||||
4. Flip-Animation, Rating-Bar (`again | hard | good | easy`)
|
||||
5. `POST /api/v1/reviews/:cardId/:subIndex/grade` mit Haptic-Feedback
|
||||
6. `PendingGrade` SwiftData-Model als Offline-Queue, Drain bei Reconnect
|
||||
7. Endurance-Test auf realem Gerät (200+ Karten, Flugmodus zwischendurch)
|
||||
|
||||
**Erfolgskriterium:** Web-Account-Decks vollständig in identischer
|
||||
Reihenfolge sichtbar, Pull-to-Refresh aktualisiert Counts.
|
||||
**Erfolgskriterium:** 50 Karten am Stück im Simulator durchgraden,
|
||||
Web zeigt nach Refresh die gleichen Reviews-States.
|
||||
|
||||
## Cross-Refs
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue