5.0 KiB
Livrets — cible desktop macOS — Plan d'implémentation
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Lancer l'app Livrets en natif sur macOS via ./gradlew :desktopApp:run, sans toucher au code existant.
Architecture: Nouveau module hôte desktopApp (kotlin-jvm + Compose Multiplatform desktop) qui dépend de :sharedUI et ouvre App(filesDirPath = ~/.livrets) dans une fenêtre 480×800 — miroir d'androidApp.
Tech Stack: Kotlin 2.4.10, Compose Multiplatform 1.12.0 (desktop), JVM 17 bytecode (JDK 18 hôte).
Spec: docs/superpowers/specs/2026-08-28-livrets-desktop-design.md
Global Constraints
- Zéro modification des modules existants (
sharedUI,androidApp,iosApp) hormissettings.gradle.kts(+include) etREADME.MD(+section) - UI texte français ; pas de commentaires dans le code ; YAGNI (pas de packaging, pas d'icône)
- Faisabilité déjà validée en sandbox sur cette machine (module,
:desktopApp:jar,:desktopApp:runavec fenêtre visible) - Tests régression :
./gradlew :sharedUI:jvmTest(20/20) doit rester vert
Task 1: Module desktopApp + lancement + README
Files:
- Modify:
settings.gradle.kts(+include) - Create:
desktopApp/build.gradle.kts,desktopApp/src/main/kotlin/com/livrets/desktop/Main.kt - Modify:
README.MD(+section macOS desktop)
Interfaces:
-
Consumes:
App(filesDirPath: String, onThemeChanged: @Composable (isDark: Boolean) -> Unit = {})(App.kt existant — signature inchangée) -
Produces: point d'entrée desktop
com.livrets.desktop.MainKt; tâches:desktopApp:run/:desktopApp:jar -
Step 1: Inclure le module et créer son build file
Dans settings.gradle.kts, après la ligne include(":androidApp"), ajouter :
include(":desktopApp")
Créer desktopApp/build.gradle.kts :
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.compose.multiplatform)
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
compilerOptions { jvmTarget.set(JvmTarget.JVM_17) }
}
dependencies {
implementation(project(":sharedUI"))
implementation(compose.desktop.currentOs)
}
compose.desktop {
application {
mainClass = "com.livrets.desktop.MainKt"
}
}
(Les alias kotlin-jvm, compose-compiler, compose-multiplatform sont déjà déclarés apply(false) à la racine ; compile.desktop.currentOs se résout via le plugin compose-multiplatform, hors catalogue.)
- Step 2: Créer le point d'entrée desktop
Créer desktopApp/src/main/kotlin/com/livrets/desktop/Main.kt :
package com.livrets.desktop
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import com.livrets.App
fun main() = application {
Window(
onCloseRequest = ::exitApplication,
title = "Livrets",
state = rememberWindowState(width = 480.dp, height = 800.dp),
) {
App(filesDirPath = storageDir())
}
}
private fun storageDir(): String =
System.getProperty("user.home") + "/.livrets"
- Step 3: Vérifier la compilation
./gradlew :desktopApp:jar :sharedUI:jvmTest
Attendu : BUILD SUCCESSFUL, 20/20 tests. (Si erreur « Inconsistent JVM Target Compatibility » : le fichier ci-dessus est déjà corrigé — vérifier que java {} ET kotlin { jvmTarget } sont bien les deux présents.)
- Step 4: Ajouter la section desktop au README
Dans README.MD, après la section ### iOS, ajouter :
### macOS desktop
Lancer l'application en fenêtre (480×800) depuis le terminal :
```bash
./gradlew :desktopApp:run
Les données sont stockées dans ~/.livrets/.
- [ ] **Step 5: Commit**
```bash
git add -A
git commit -m "feat: cible desktop macOS via :desktopApp:run"
- Step 6: Vérification du lancement (contrôleur ou utilisateur)
./gradlew :desktopApp:run
Attendu : fenêtre « Livrets » 480×800, écran d'accueil avec les 3 réglages. Fermer la fenêtre arrête le processus. (Bloque jusqu'à fermeture — à lancer de façon interactive, pas dans la boucle de tests.)
Notes d'exécution
- Ne pas toucher à
sharedUI/androidApp/iosApp— si:desktopApp:jarrévèle une incompatibilité, rapporter BLOCKED avec la sortie exacte. :desktopApp:runest interactif (fenêtre bloquante) : la vérification automatisée =:desktopApp:jar+ processus JVM vivant pendant un run en arrière-plan ; la confirmation visuelle finale revient à l'utilisateur.~/.livretsest créé à la première partie terminée (HistoryRepository.createDirectories) ; l'écran Historique affiche « Aucune partie enregistrée » avant.