# 2.1 — Domaine de lecture ## Objectif Modéliser le cœur métier de la lecture : ce qu'est une histoire jouable et l'état de lecture, indépendamment de toute techno audio. ## Périmètre & hors-périmètre - Inclus : entités, value objects, interface `PlaybackRepository`, use cases. - Exclus : implémentation audio (2.2), UI (2.3). ## Dépendances Jalon 0. ## Conception - **Domain** (`features/playback/domain/`) : - `Episode` (entité) : `id`, `title`, `audioUrl`, `duration?`, `artworkUrl?`. Immuable. - `PlaybackState` (value object) : `status` (`idle`/`loading`/`playing`/`paused`/`completed`/`error`), `current` (`Episode?`), `position`, `bufferedPosition`. - `PlaybackRepository` (interface) : - `Future> load(List queue, {int startIndex})` - `Future> play()` / `pause()` / `next()` / `previous()` - `Future> seek(Duration position)` - `Stream watch()` - `PlaybackFailure` : `AudioSourceFailure`, `PlaybackUnavailableFailure`. - **Application** (`features/playback/application/`) : - `PlayStoryUseCase` (charge la file + démarre à l'index voulu). - `TogglePlayPauseUseCase`, `SkipNextUseCase`, `SkipPreviousUseCase`, `SeekUseCase`. - `WatchPlaybackStateUseCase`. ## Plan TDD 1. **Red** : `playback_state_test.dart` — `copyWith`, transitions et égalité (immuabilité) de `PlaybackState`. 2. **Green** : implémenter entités/value objects. 3. **Red** : `play_story_use_case_test.dart` — avec `PlaybackRepository` mocké : charge la file et appelle `play` ; index hors bornes → `Err`. 4. **Green** : implémenter le use case. 5. **Red** : use cases toggle/skip/seek — vérifient l'appel correct au repo selon l'état. 6. **Green** : implémenter. 7. **Refactor**. ## Definition of Done - Tests domaine + use cases verts, sans import Flutter/just_audio. - `tool/check.sh` passe ; étape 2.1 cochée dans `ROADMAP.md`. ## Risques / notes - `Episode` est volontairement minimal ; J3 fournira de quoi le construire depuis un flux RSS. Garder le mapping RSS→Episode dans la feature `podcasts`, pas ici.