Lecteur d'histoires cadenassé pour le coucher (Android/Flutter). - CLAUDE.md : principes craftsmanship/TDD/clean code/clean archi + decisions techniques - ROADMAP.md : suivi haut niveau des 7 jalons, a tenir a jour par etape - docs/specs/ : specs completes decoupees par jalon, etapes en sous-fichiers - .gitignore Flutter (pubspec.lock versionne, projet applicatif) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3.5 KiB
Vision & architecture
Vision produit
Storytime transforme une tablette Android en lecteur d'histoires du soir cadenassé. L'enfant choisit et écoute des histoires (épisodes de podcasts) sans pouvoir sortir de l'application ni accéder au reste de la tablette. Le parent garde le contrôle : il sélectionne les sources, définit un code parental et fixe des limites (temps / nombre d'histoires) adaptées au rituel du coucher.
Utilisateurs
- Enfant (sait lire, choisit par le titre) : interface minimale, gros boutons.
- Parent : configuration protégée par code 4 chiffres.
Périmètre v1
Inclus : lecture en streaming, recherche annuaire + ajout RSS, liste d'histoires, épinglage, code parental, limites (temps + nombre) avec avertissements doux. Exclus v1 : téléchargement hors-ligne, multi-profils enfants, multi-plateforme, récupération de code par question secrète (réinstaller réinitialise).
Architecture cible
Clean Architecture, feature-first. Détail des couches et de la règle de dépendance
dans ../../CLAUDE.md §3-4. Rappel du flux :
Presentation (Riverpod/UI) → Application (use cases) → Domain ← Data (infra)
Features et leurs responsabilités
| Feature | Responsabilité | Dépendances externes (couche data) |
|---|---|---|
locking |
Épingler/désépingler l'app, état de verrouillage | plugin kiosk_mode / channel Kotlin |
playback |
Lire un épisode, pause, suivant, progression | just_audio, audio_service |
podcasts |
Rechercher, ajouter (RSS), persister les abonnements, lister les épisodes | iTunes Search, dart_rss, SQLite |
parental |
Créer/vérifier le code, garder l'accès parent | flutter_secure_storage |
limits |
Compter temps & histoires, avertir, arrêter, reset quotidien | shared_preferences |
Flux de données type (lecture d'une histoire)
presentation(écran enfant) lit la liste viaListEpisodesUseCase.- L'enfant tape un titre →
PlayStoryUseCase(application) demande auPlaybackRepository(domain) de jouer ; l'impl. (data) pilotejust_audio. limitsobserve les événements de lecture (histoire démarrée, temps écoulé) et déclenche avertissements / arrêt.lockingmaintient l'épinglage tout au long.
Principes transverses
- Result/Failure plutôt qu'exceptions traversantes (cf. CLAUDE.md §4).
- Immuabilité des entités et états.
- DI par Riverpod ; tout est overridable en test.
- Messages enfant rassurants, jamais d'erreur technique brute à l'écran enfant.
- Honnêteté de l'UI sur le verrouillage : ne pas laisser croire à une protection plus forte que ce que l'épinglage natif offre réellement.
Ordre de construction & dépendances
- J0 pose le squelette → prérequis de tout.
- J1 valide l'épinglage → bloquant : conditionne la viabilité du produit.
- J2 lecture audio (testable avec un flux en dur).
- J3 podcasts (recherche + RSS + persistance).
- J4 espace enfant : consomme J2 (lecture) + J3 (liste) + J1 (verrouillage).
- J5 code parental + espace parent : abrite la gestion podcasts de J3 derrière le code.
- J6 limites : s'appuie sur les événements de J2 et l'arrêt/reprise gérés avec J5.
Note de dépendance J3↔J5 : J3 construit le domaine podcasts + un écran d'accès temporaire (dev) ; J5 déplace cet accès derrière la porte parentale. Documenté dans les specs concernées.